From e881837962449d66d91048ed16bc9ca44368af29 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Wed, 4 Sep 2024 10:30:03 +0100 Subject: [PATCH 01/10] removed SSG --- CMakeLists.txt | 9 - bin/bedrock-query.cpp | 30 +- include/bedrock/Client.hpp | 28 -- include/bedrock/DependencyFinder.hpp | 12 +- include/bedrock/SSGManager.hpp | 180 -------- include/bedrock/Server.hpp | 6 - include/bedrock/ServiceHandle.hpp | 11 - python/mochi/bedrock/bedrockctl/__main__.py | 3 - python/mochi/bedrock/bedrockctl/_util.py | 19 +- python/mochi/bedrock/bedrockctl/ssg.py | 118 ----- python/mochi/bedrock/client.py | 16 +- python/mochi/bedrock/server.py | 53 +-- python/mochi/bedrock/spec.py | 192 -------- python/mochi/bedrock/test_dependencies.py | 98 ---- python/mochi/bedrock/test_server.py | 2 +- .../bedrock/test_service_group_handle.py | 61 +-- python/mochi/bedrock/test_service_handle.py | 39 +- python/mochi/bedrock/test_ssg_manager.py | 99 ---- python/src/py-bedrock-client.cpp | 22 - python/src/py-bedrock-server.cpp | 50 -- src/CMakeLists.txt | 3 - src/Client.cpp | 21 - src/ClientImpl.hpp | 2 - src/DependencyFinder.cpp | 64 +-- src/DependencyFinderImpl.hpp | 2 - src/SSGManager.cpp | 428 ------------------ src/SSGManagerImpl.hpp | 185 -------- src/Server.cpp | 14 +- src/ServerImpl.hpp | 19 - src/ServiceGroupHandleImpl.hpp | 90 ---- src/ServiceHandle.cpp | 8 - src/bedrock-config.cmake.in | 3 - tests/ValidConfigs.json | 28 +- 33 files changed, 62 insertions(+), 1853 deletions(-) delete mode 100644 include/bedrock/SSGManager.hpp delete mode 100644 python/mochi/bedrock/bedrockctl/ssg.py delete mode 100644 python/mochi/bedrock/test_ssg_manager.py delete mode 100644 src/SSGManager.cpp delete mode 100644 src/SSGManagerImpl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 33ed898..b1a2403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,6 @@ option (ENABLE_TESTS "Build tests" OFF) option (ENABLE_EXAMPLES "Build examples" OFF) option (ENABLE_MPI "Enable MPI support" OFF) option (ENABLE_MONA "Enable MoNA support" OFF) -option (ENABLE_SSG "Enable SSG support" OFF) option (ENABLE_FLOCK "Enable Flock support" OFF) option (ENABLE_ABT_IO "Enable ABT-IO support" OFF) option (ENABLE_PYTHON "Enable Python support" OFF) @@ -81,14 +80,6 @@ if (ENABLE_ABT_IO) set (OPTIONAL_ABT_IO PkgConfig::ABTIO) set (OPTIONAL_SERVER_DEPS "${OPTIONAL_SERVER_DEPS} abt-io") endif () -# search for ssg -if (ENABLE_SSG) - pkg_check_modules (SSG REQUIRED IMPORTED_TARGET ssg) - add_definitions (-DENABLE_SSG) - set (OPTIONAL_SSG PkgConfig::SSG) - set (OPTIONAL_SERVER_DEPS "${OPTIONAL_SERVER_DEPS} ssg") - set (OPTIONAL_CLIENT_DEPS "${OPTIONAL_CLIENT_DEPS} ssg") -endif () if (ENABLE_FLOCK) find_package (flock REQUIRED) add_definitions (-DENABLE_FLOCK) diff --git a/bin/bedrock-query.cpp b/bin/bedrock-query.cpp index 3d56325..376a633 100644 --- a/bin/bedrock-query.cpp +++ b/bin/bedrock-query.cpp @@ -1,8 +1,5 @@ #include #include -#ifdef ENABLE_SSG -#include -#endif #include #include #include @@ -20,7 +17,6 @@ using nlohmann::json; static std::string g_protocol; static std::vector g_addresses; static std::string g_log_level; -static std::string g_ssg_file; static std::string g_flock_file; static std::string g_jx9_file; static std::string g_jx9_script_content; @@ -47,10 +43,6 @@ int main(int argc, char** argv) { try { auto engine = thallium::engine(g_protocol, THALLIUM_CLIENT_MODE); -#ifdef ENABLE_SSG - ssg_init(); -#endif - if(!g_flock_file.empty()) { json flock_file_content; std::ifstream flock_file{g_flock_file}; @@ -70,8 +62,7 @@ int main(int argc, char** argv) { bedrock::Client client(engine); - auto sgh = g_ssg_file.empty() ? client.makeServiceGroupHandle(g_addresses, g_provider_id) - : client.makeServiceGroupHandleFromSSGFile(g_ssg_file, g_provider_id); + auto sgh = client.makeServiceGroupHandle(g_addresses, g_provider_id); std::string result; if (g_jx9_script_content.empty()) @@ -79,9 +70,6 @@ int main(int argc, char** argv) { else sgh.queryConfig(g_jx9_script_content, &result); std::cout << (g_pretty ? json::parse(result).dump(4) : result) << std::endl; -#ifdef ENABLE_SSG - ssg_finalize(); -#endif } catch (const std::exception& e) { spdlog::critical(e.what()); exit(-1); } return 0; } @@ -106,12 +94,6 @@ static void parseCommandLine(int argc, char** argv) { "f", "flock-file", "Flock file from which to read addresses of Bedrock daemons", false, "", "filename"); -#ifdef ENABLE_SSG - TCLAP::ValueArg ssgFile( - "s", "ssg-file", - "SSG file from which to read addresses of Bedrock daemons", false, - "", "filename"); -#endif TCLAP::ValueArg jx9File( "j", "jx9-file", "Jx9 file to send to processes and execute", false, "", "filename"); @@ -122,9 +104,6 @@ static void parseCommandLine(int argc, char** argv) { cmd.add(protocol); cmd.add(logLevel); cmd.add(flockFile); -#ifdef ENABLE_SSG - cmd.add(ssgFile); -#endif cmd.add(providerID); cmd.add(addresses); cmd.add(prettyJSON); @@ -133,15 +112,12 @@ static void parseCommandLine(int argc, char** argv) { g_addresses = addresses.getValue(); g_log_level = logLevel.getValue(); g_flock_file = flockFile.getValue(); -#ifdef ENABLE_SSG - g_ssg_file = ssgFile.getValue(); -#endif g_protocol = protocol.getValue(); g_provider_id = providerID.getValue(); g_pretty = prettyJSON.getValue(); g_jx9_file = jx9File.getValue(); - if(!g_addresses.empty() && !g_ssg_file.empty()) { - std::cerr << "error: specifying -s and -a at the same time is not supported" << std::endl; + if(g_addresses.empty()) { + std::cerr << "error: no address specified" << std::endl; exit(-1); } } catch (TCLAP::ArgException& e) { diff --git a/include/bedrock/Client.hpp b/include/bedrock/Client.hpp index a18cb02..bcef983 100644 --- a/include/bedrock/Client.hpp +++ b/include/bedrock/Client.hpp @@ -92,34 +92,6 @@ class Client { const std::string& address, uint16_t provider_id=0) const; - /** - * @brief Creates a handle to a group of Bedrock processes - * from an SSG group file. - * - * @important SSG needs to have been initialized for this - * function to work, otherwise an exception will be returned. - * - * @param groupfile SSG group file. - * @param provider_id Provider ID of the bedrock providers. - * - * @return ServiceGroupHandle instance. - */ - ServiceGroupHandle makeServiceGroupHandleFromSSGFile( - const std::string& groupfile, - uint16_t provider_id=0) const; - - /** - * @brief Creates a handle to a group of Bedrock processes. - * - * @param gid Existing SSG group id. - * @param provider_id Provider ID of the bedrock providers. - * - * @return ServiceGroupHandle instance. - */ - ServiceGroupHandle makeServiceGroupHandleFromSSGGroup( - uint64_t gid, - uint16_t provider_id=0) const; - /** * @brief Creates a handle to a group of Bedrock processes * from an Flock group file. diff --git a/include/bedrock/DependencyFinder.hpp b/include/bedrock/DependencyFinder.hpp index 41988cc..5c448f3 100644 --- a/include/bedrock/DependencyFinder.hpp +++ b/include/bedrock/DependencyFinder.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -40,13 +39,13 @@ class DependencyFinder { * @param mpi MPI context * @param margo Margo context * @param abtio ABT-IO context - * @param ssg SSG context * @param pmanager Provider manager * @param cmanager Client manager */ DependencyFinder(const MPIEnv& mpi, - const MargoManager& margo, const ABTioManager& abtio, - const SSGManager& ssg, const MonaManager& mona, + const MargoManager& margo, + const ABTioManager& abtio, + const MonaManager& mona, const ProviderManager& pmanager, const ClientManager& cmanager); @@ -93,7 +92,6 @@ class DependencyFinder { * SPECIFIER := NAME * | TYPE ':' ID * LOCATION := ADDRESS - * | 'ssg://' NAME '/' RANK * ADDRESS := * NAME := * ID := @@ -170,7 +168,7 @@ class DependencyFinder { * right type) * @param type Type of service. * @param provider_id Provider id - * @param locator Location (e.g. "local" or mercury or ssg addresses) + * @param locator Location (e.g. "local" or mercury address) * @param resolved Output resolved specification * * @return An abstract pointer to the dependency. @@ -193,7 +191,7 @@ class DependencyFinder { * right type) * @param type Type of service. * @param name Name of the provider - * @param locator Location (e.g. "local" or mercury or ssg addresses) + * @param locator Location (e.g. "local" or mercury addresses) * @param resolved Output resolved specification * * @return An abstract pointer to the dependency. diff --git a/include/bedrock/SSGManager.hpp b/include/bedrock/SSGManager.hpp deleted file mode 100644 index edd29af..0000000 --- a/include/bedrock/SSGManager.hpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_SSG_MANAGER_HPP -#define __BEDROCK_SSG_MANAGER_HPP - -#include -#include -#include -#include - -typedef uint64_t ssg_group_id_t; -typedef uint64_t ssg_member_id_t; -typedef struct ssg_group_config ssg_group_config_t; - -namespace bedrock { - -class Server; -class ServerImpl; -class DependencyFinder; -class SSGManagerImpl; -class SSGUpdateHandler; -class Jx9Manager; - -/** - * @brief The SSGManager class encapsulates an ssg_group_id_t. - */ -class SSGManager { - - friend class Server; - friend class ServerImpl; - friend class DependencyFinder; - friend class SSGUpdateHandler; - - using json = nlohmann::json; - - public: - /** - * @brief Constructor from a JSON configurations string. - * - * @param margo MargoManager - * @param jx9 Jx9Manager - * @param config JSON configuration. - */ - SSGManager(const MargoManager& margo, - const Jx9Manager& jx9, - const json& config = json::object()); - - /** - * @brief Copy-constructor. - */ - SSGManager(const SSGManager&); - - /** - * @brief Move-constructor. - */ - SSGManager(SSGManager&&); - - /** - * @brief Copy-assignment operator. - */ - SSGManager& operator=(const SSGManager&); - - /** - * @brief Move-assignment operator. - */ - SSGManager& operator=(SSGManager&&); - - /** - * @brief Destructor. - */ - ~SSGManager(); - - /** - * @brief Checks whether the SSGManager instance is valid. - */ - operator bool() const; - - /** - * @brief Create a group from a JSON configuration. - * - * @param description JSON description of the group. - * - * @return The created group as a NamedDependency. - * - * Example of JSON description: - * - * ```json - * { - * "name": "my_ssg_group", - * "pool": "my_pool", - * "credential": 1234, - * "group_file": "/path/to/group/file.ssg", - * "bootstrap": "init|join", - * "swim": { - * "period_length_ms": 500, - * "suspect_timeout_periods": 3, - * "subgroup_member_count": 5 - * } - * } - * ``` - */ - std::shared_ptr - addGroupFromJSON(const json& description); - - /** - * @brief Create a group and add it to the SSG context. - * - * @param name Name of the group. - * @param config Configuration. - * @param pool Pool. - * @param bootstrap_method Bootstrap method. - * @param group_file Group file to create for other processes to join. - * - * @return The newly created SSG group. - */ - std::shared_ptr - addGroup(const std::string& name, - const ssg_group_config_t& config, - const std::shared_ptr& pool, - const std::string& bootstrap_method, - const std::string& group_file = ""); - - /** - * @brief Get an internal SSG group by its name. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the group. - */ - std::shared_ptr getGroup(const std::string& group_name) const; - - /** - * @brief Get an internal SSG group by its index. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the group. - */ - std::shared_ptr getGroup(size_t index) const; - - /** - * @brief Get the number of groups. - */ - size_t getNumGroups() const; - - /** - * @brief Resolve an address starting with ssg:// - * These address may be: - * - ssg:///members/ - * - ssg:///ranks/ - * This function will throw an exception if the address - * could not be resolved. The caller is NOT supposed to - * destroy the returned hg_addr_t. - * - * @param address Address - * - * @return the corresponding hg_addr_t. - */ - hg_addr_t resolveAddress(const std::string& address) const; - - /** - * @brief Return the current JSON configuration. - */ - json getCurrentConfig() const; - - private: - std::shared_ptr self; - - inline operator std::shared_ptr() const { return self; } - - inline SSGManager(std::shared_ptr impl) - : self(std::move(impl)) {} -}; - -} // namespace bedrock - -#endif diff --git a/include/bedrock/Server.hpp b/include/bedrock/Server.hpp index f9fbbd5..039bf43 100644 --- a/include/bedrock/Server.hpp +++ b/include/bedrock/Server.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -100,11 +99,6 @@ class Server { */ ClientManager getClientManager() const; - /** - * @brief Get the underlying SSG context. - */ - SSGManager getSSGManager() const; - /** * @brief Blocks until the underlying margo instance is finalized. */ diff --git a/include/bedrock/ServiceHandle.hpp b/include/bedrock/ServiceHandle.hpp index a67173d..078f8a0 100644 --- a/include/bedrock/ServiceHandle.hpp +++ b/include/bedrock/ServiceHandle.hpp @@ -180,17 +180,6 @@ class ServiceHandle { void addABTioInstance(const std::string& description, AsyncRequest* req = nullptr) const; - /** - * @brief Adds an SSG group to the target service daemon. - * The group is created from the provided JSON configuration. - * - * @param description JSON description. - * @param req Asynchronous request to wait on, if provided. - */ - void addSSGgroup(const std::string& config, - AsyncRequest* req = nullptr) const; - - /** * @brief Adds an Argobots pool to the Margo instance of * the target service. diff --git a/python/mochi/bedrock/bedrockctl/__main__.py b/python/mochi/bedrock/bedrockctl/__main__.py index 63fb13e..d130ae3 100644 --- a/python/mochi/bedrock/bedrockctl/__main__.py +++ b/python/mochi/bedrock/bedrockctl/__main__.py @@ -27,9 +27,6 @@ from .mona import app as mona_app app.add_typer(mona_app, name="mona", help="Access and modify MoNA instances") -from .ssg import app as ssg_app -app.add_typer(ssg_app, name="ssg", help="Access and modify SSG groups") - @app.command() def status(): diff --git a/python/mochi/bedrock/bedrockctl/_util.py b/python/mochi/bedrock/bedrockctl/_util.py index b3f8365..32b6845 100644 --- a/python/mochi/bedrock/bedrockctl/_util.py +++ b/python/mochi/bedrock/bedrockctl/_util.py @@ -7,7 +7,6 @@ class ServiceContext: - ssg_prefix = "ssg://" flock_prefix = "flock://" def __init__(self, target=None): @@ -15,14 +14,6 @@ def __init__(self, target=None): if self.connection is None: print(f"Error: bedrockctl not connected") raise typer.Exit(code=-1) - # SSG file - if self.connection.startswith(ServiceContext.ssg_prefix): - group_file = self.connection[len(ServiceContext.ssg_prefix):] - if not (os.path.exists(group_file) and os.path.isfile(group_file)): - print(f"Error: could not access SSG file {group_file}") - raise typer.Exit(code=-1) - import pyssg - self.protocol = pyssg.get_group_transport_from_file(group_file) # Flock file elif self.connection.startswith(ServiceContext.flock_prefix): group_file = self.connection[len(ServiceContext.flock_prefix):] @@ -58,12 +49,7 @@ def __init__(self, target=None): def __enter__(self): self.engine = Engine(self.protocol) client = Client(self.engine) - if self.connection.startswith(ServiceContext.ssg_prefix): - import pyssg - pyssg.init() - self.service = client.make_service_group_handle_from_ssg( - self.connection[len(ServiceContext.ssg_prefix):]) - elif self.connection.startswith(ServiceContext.flock_prefix): + if self.connection.startswith(ServiceContext.flock_prefix): self.service = client.make_service_group_handle_from_flock( self.connection[len(ServiceContext.flock_prefix):]) else: @@ -73,9 +59,6 @@ def __enter__(self): def __exit__(self, type, value, traceback): self.service = None del self.service - if self.connection.startswith(ServiceContext.ssg_prefix): - import pyssg - pyssg.finalize() self.engine.finalize() diff --git a/python/mochi/bedrock/bedrockctl/ssg.py b/python/mochi/bedrock/bedrockctl/ssg.py deleted file mode 100644 index 7dd2af8..0000000 --- a/python/mochi/bedrock/bedrockctl/ssg.py +++ /dev/null @@ -1,118 +0,0 @@ -import typer -from typing_extensions import Annotated -from enum import Enum -from typing import Optional, List -from ..spec import PoolSpec -from ..client import ClientException - - -app = typer.Typer() - - -@app.command() -def create( - name: Annotated[ - str, typer.Argument(help="Name of the SSG group to create")], - file: Annotated[ - str, typer.Option( - "-f", "--file", help="Group file")], - pool: Annotated[ - str, typer.Option( - "-p", "--pool", help="Pool for the SSG group to use")] = "__primary__", - disable_swim: Annotated[ - bool, typer.Option("--disable-swim/--enable-swim", - help="Disable SWIM protocol")] = False, - swim_period_length_ms: Annotated[ - int, typer.Option(help="SWIM period length in milliseconds")] = 0, - swim_suspect_timeout_periods: Annotated[ - int, typer.Option(help="SWIM number of suspect timeout periods")] = -1, - swim_subgroup_member_count: Annotated[ - int, typer.Option(help="SWIM subgroup member count")] = -1, - credential: Annotated[int, typer.Option(help="Credential")] = -1, - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Create a new SSG group in the target Bedrock process(es). - """ - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - ssg_group = { - "name": name, - "pool": pool, - "group_file": file, - "credential": credential, - "bootstrap": "init", - "swim": { - "disabled": disable_swim, - "period_length_ms": swim_period_length_ms, - "suspect_timeout_periods": swim_suspect_timeout_periods, - "subgroup_member_count": swim_subgroup_member_count - } - } - from ._util import ServiceContext - with ServiceContext(target) as service: - # TODO: for now we need the first rank to "init" the group - # then the next processes need to "join" it. It would be - # better to be able to add a list of addresses as agument. - for i in range(0, len(service)): - if not rank_is_in(i, ranks): - continue - try: - service[i].add_ssg_group(ssg_group) - ssg_group["bootstrap"] = "join" - except ClientException as e: - print(f"Error adding SSG group in {service[i].address}: {str(e)}") - if i == 0: - raise typer.Exit(code=-1) - del service - - -@app.command() -def list(target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Lists the SSG groups in each of the target Bedrock process(es). - """ - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import ServiceContext - from rich import print - with ServiceContext(target) as service: - config = { a: c["ssg"] for a, c in service.config.items() } - for i in range(len(service)): - if not rank_is_in(i, ranks): - del config[service[i].address] - print(config) - del service - - -@app.command() -def remove( - name: Annotated[ - str, typer.Argument(help="Name of the SSG group to remove")], - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Remove an SSG group from the target Bedrock process(es). - """ - print("This command is not implemented yet") - raise typer.Exit(code=-1) - - -if __name__ == "__main__": - app() diff --git a/python/mochi/bedrock/client.py b/python/mochi/bedrock/client.py index a557136..0d35e0a 100644 --- a/python/mochi/bedrock/client.py +++ b/python/mochi/bedrock/client.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo import json -from .spec import ProcSpec, XstreamSpec, PoolSpec, AbtIOSpec, SSGSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, XstreamSpec, PoolSpec, AbtIOSpec, ProviderSpec, ClientSpec ClientException = pybedrock_client.Exception @@ -76,10 +76,6 @@ def add_xstream(self, config: str|dict|XstreamSpec): def remove_xstream(self, name: str): self._internal.remove_xstream(name) - def add_ssg_group(self, description: str|dict|SSGSpec): - description = self._ensure_config_str(description) - self._internal.add_ssg_group(description) - def add_abtio_instance(self, description: str|dict|AbtIOSpec): description = self._ensure_config_str(description) self._internal.add_abtio_instance(description) @@ -174,16 +170,6 @@ def make_service_group_handle(self, addresses: list[str], provider_id: int = 0): self._internal.make_service_group_handle(addresses, provider_id), self) - def make_service_group_handle_from_ssg(self, group: str|int, provider_id: int = 0): - if isinstance(group, int): - return ServiceGroupHandle( - self._internal.make_service_group_handle_from_ssg_group(group, provider_id), - self) - else: - return ServiceGroupHandle( - self._internal.make_service_group_handle_from_ssg_file(group, provider_id), - self) - def make_service_group_handle_from_flock(self, groupfile: str, provider_id: int = 0): return ServiceGroupHandle( self._internal.make_service_group_handle_from_flock_file(groupfile, provider_id), diff --git a/python/mochi/bedrock/server.py b/python/mochi/bedrock/server.py index 27443a5..cb4ff1a 100644 --- a/python/mochi/bedrock/server.py +++ b/python/mochi/bedrock/server.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo from typing import Mapping, List -from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, SSGSpec, AbtIOSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, AbtIOSpec, ProviderSpec, ClientSpec import json @@ -48,7 +48,6 @@ def handle(self): Pool = NamedDependency Xstream = NamedDependency -SSGGroup = NamedDependency AbtIOInstance = NamedDependency Client = NamedDependency @@ -164,52 +163,6 @@ def default_handler_pool(self): return Pool(self._internal.default_handler_pool) -class SSGManager: - - def __init__(self, internal: pybedrock_server.SSGManager, server: 'Server'): - self._internal = internal - self._server = server - - @property - def config(self): - return json.loads(self._internal.config) - - @property - def spec(self) -> list[SSGSpec]: - abt_spec = self._server.margo.spec.argobots - return [SSGSpec.from_dict(group, abt_spec) for group in self.config] - - def resolve(self, location: str) -> pymargo.core.Address: - mid = self._server.margo.mid - return pymargo.core.Address( - mid=mid, hg_addr=self._internal.resolve_address(location), - need_del=False).copy() - - def __len__(self) -> int: - return self._internal.num_groups - - def __getitem__(self, key: int|str) -> SSGGroup: - return SSGGroup(self._internal.get_group(key)) - - def __contains__(self, key: str) -> bool: - try: - self.__getitem__(key) - return True - except BedrockException: - return False - - def create(self, name: str, pool: str|int|Pool = "__primary__", - config: str|dict|SSGSpec = "{}", - bootstrap: str = "init", group_file: str = "", - credential: int = -1) -> SSGGroup: - if not isinstance(pool, Pool): - pool = self._server.margo.pools[pool] - pool = pool._internal - if isinstance(config, str): - config = json.loads(config) - return SSGGroup(self._internal.add_group(name, config, pool, bootstrap, group_file, credential)) - - class AbtIOManager: def __init__(self, internal: pybedrock_server.ABTioManager, server: 'Server'): @@ -409,10 +362,6 @@ def spec(self) -> ProcSpec: def margo(self) -> MargoManager: return MargoManager(self._internal.margo_manager, self) - @property - def ssg(self) -> SSGManager: - return SSGManager(self._internal.ssg_manager, self) - @property def abtio(self) -> AbtIOManager: return AbtIOManager(self._internal.abtio_manager, self) diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index 0697426..8536d09 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -1516,172 +1516,6 @@ def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'MonaSpec': return MonaSpec.from_dict(json.loads(json_string), abt_spec) -@attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) -class SwimSpec: - """Swim specification for SSG. - - :param period_length_ms: Period length in milliseconds - :type period_length_ms: int - - :param suspect_timeout_periods: Number of suspect timeout periods - :type suspect_timeout_periods: int - - :param subgroup_member_count: Subgroup member count - :type subgroup_member_count: int - - :param disabled: Disable Swim - :type disabled: bool - """ - - period_length_ms: int = attr.ib( - validator=instance_of(int), - default=0) - suspect_timeout_periods: int = attr.ib( - validator=instance_of(int), - default=-1) - subgroup_member_count: int = attr.ib( - validator=instance_of(int), - default=-1) - disabled: bool = attr.ib( - validator=instance_of(bool), - default=False) - - def to_dict(self) -> dict: - """Convert the SwimSpec into a dictionary. - """ - return attr.asdict(self) - - @staticmethod - def from_dict(data: dict) -> 'SwimSpec': - """Construct a SwimSpec from a dictionary. - """ - return SwimSpec(**data) - - def to_json(self, *args, **kwargs) -> str: - """Convert the SwimSpec into a JSON string. - """ - return json.dumps(self.to_dict(), *args, **kwargs) - - @staticmethod - def from_json(json_string: str) -> 'SwimSpec': - """Construct a SwimSpec from a JSON string. - """ - data = json.loads(json_string) - return SwimSpec.from_dict(data) - - def validate(self) -> NoReturn: - """Validate the state of the MercurySpec, raising an exception - if the MercurySpec is not valid. - """ - attr.validate(self) - - -def _swim_from_args(arg) -> SwimSpec: - """Construct a SwimSpec from a single argument. If the argument - if a dict, its content if forwarded to the SwimSpec constructor. - """ - if isinstance(arg, SwimSpec): - return arg - elif isinstance(arg, dict): - return MargoSpec(**arg) - elif arg is None: - return SwimSpec(disabled=True) - else: - raise TypeError(f'cannot convert type {type(arg)} into a SwimSpec') - - -@attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) -class SSGSpec: - """SSG group specification. - - :param name: Name of the SSG group - :type name: str - - :param pool: Pool associated with the group - :type pool: PoolSpec - - :param credential: Credentials - :type credential: long - - :param bootstrap: Bootstrap method - :type bootstrap: str - - :param group_file: Group file - :type group_file: str - - :param swim: Swim parameters - :type swim: SwimSpec - """ - - name: str = attr.ib( - validator=[instance_of(str), _validate_object_name], - on_setattr=attr.setters.frozen) - pool: PoolSpec = attr.ib( - validator=instance_of(PoolSpec)) - credential: int = attr.ib( - validator=instance_of(int), - default=-1) - bootstrap: str = attr.ib( - validator=in_(['init', 'join', 'mpi', 'pmix', 'init|join', 'mpi|join', 'pmix|join'])) - group_file: str = attr.ib( - validator=instance_of(str), - default='') - swim: Optional[SwimSpec] = attr.ib( - validator=instance_of(SwimSpec), - converter=_swim_from_args, - default=None) - - def to_dict(self) -> dict: - """Convert the SSGSpec into a dictionary. - """ - result = {'name': self.name, - 'pool': self.pool.name, - 'credential': self.credential, - 'bootstrap': self.bootstrap, - 'group_file': self.group_file} - if self.swim is not None: - result['swim'] = self.swim.to_dict() - return result - - @staticmethod - def from_dict(data: dict, abt_spec: ArgobotsSpec) -> 'SSGSpec': - """Construct an SSGSpec from a dictionary. Since the dictionary - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param data: Dictionary - :type data: dict - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - args = data.copy() - args['pool'] = abt_spec.pools[data['pool']] - if 'swim' in args: - args['swim'] = SwimSpec.from_dict(args['swim']) - ssg = SSGSpec(**args) - return ssg - - def to_json(self, *args, **kwargs) -> str: - """Convert the SSGSpec into a JSON string. - """ - return json.dumps(self.to_dict(), *args, **kwargs) - - @staticmethod - def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'SSGSpec': - """Construct an SSGSpec from a JSON string. Since the JSON string - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param json_string: JSON string - :type json_string: str - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - return SSGSpec.from_dict(json.loads(json_string), abt_spec) - - @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class ProviderSpec: """Provider specification. @@ -2000,9 +1834,6 @@ class ProcSpec: :param mona: List of MonaSpec :type mona: list - :param ssg: List of SSGSpec - :type ssg: list - :param libraries: Dictionary of libraries :type libraries: dict @@ -2022,9 +1853,6 @@ class ProcSpec: _mona: List[MonaSpec] = attr.ib( factory=list, validator=instance_of(list)) - _ssg: List[SSGSpec] = attr.ib( - factory=list, - validator=instance_of(list)) libraries: dict = attr.ib( factory=dict, validator=instance_of(dict)) @@ -2053,13 +1881,6 @@ def mona(self) -> SpecListDecorator: """ return SpecListDecorator(list=self._mona, type=MonaSpec) - @property - def ssg(self) -> SpecListDecorator: - """Return a decorator to access the internal list of SSGSpec - and validate changes to this list. - """ - return SpecListDecorator(list=self._ssg, type=SSGSpec) - @property def providers(self) -> SpecListDecorator: """Return a decorator to access the internal list of ProviderSpec @@ -2079,7 +1900,6 @@ def to_dict(self) -> dict: """ data = {'margo': self.margo.to_dict(), 'abt_io': [a.to_dict() for a in self._abt_io], - 'ssg': [g.to_dict() for g in self._ssg], 'mona': [m.to_dict() for m in self._mona], 'libraries': self.libraries, 'providers': [p.to_dict() for p in self._providers], @@ -2094,7 +1914,6 @@ def from_dict(data: dict) -> 'ProcSpec': margo = MargoSpec.from_dict(data['margo']) abt_io = [] mona = [] - ssg = [] libraries = dict() providers = [] bedrock = {} @@ -2104,9 +1923,6 @@ def from_dict(data: dict) -> 'ProcSpec': if 'abt_io' in data: for a in data['abt_io']: abt_io.append(AbtIOSpec.from_dict(a, margo.argobots)) - if 'ssg' in data: - for g in data['ssg']: - ssg.append(SSGSpec.from_dict(g, margo.argobots)) if 'mona' in data: for m in data['mona']: mona.append(MonaSpec.from_dict(m, margo.argobots)) @@ -2120,7 +1936,6 @@ def from_dict(data: dict) -> 'ProcSpec': bedrock = BedrockSpec.from_dict(data['bedrock'], margo.argobots) return ProcSpec(margo=margo, abt_io=abt_io, - ssg=ssg, mona=mona, libraries=libraries, providers=providers, @@ -2152,11 +1967,6 @@ def validate(self) -> NoReturn: if p not in self.margo.argobots.pools: raise ValueError(f'Pool "{p.name}" used by MoNA instance' + ' not found in margo.argobots.pools') - for g in self._ssg: - p = g.pool - if p not in self.margo.argobots.pools: - raise ValueError(f'Pool "{p.name}" used by SSG group' + - ' not found in margo.argobots.pool') for k, v in self.libraries.items(): if not isinstance(k, str): raise TypeError('Invalid key type found in libraries' + @@ -2415,8 +2225,6 @@ def from_config(config: 'Configuration', attr.resolve_types(ProviderSpec, globals(), locals()) attr.resolve_types(ClientSpec, globals(), locals()) attr.resolve_types(AbtIOSpec, globals(), locals()) -attr.resolve_types(SwimSpec, globals(), locals()) -attr.resolve_types(SSGSpec, globals(), locals()) attr.resolve_types(BedrockSpec, globals(), locals()) attr.resolve_types(ProcSpec, globals(), locals()) attr.resolve_types(ServiceSpec, globals(), locals()) diff --git a/python/mochi/bedrock/test_dependencies.py b/python/mochi/bedrock/test_dependencies.py index a2c8a9e..967e04c 100644 --- a/python/mochi/bedrock/test_dependencies.py +++ b/python/mochi/bedrock/test_dependencies.py @@ -56,13 +56,6 @@ def setUp(self): "pool": "__primary__" } ], - "ssg": [ - { - "name": "my_ssg", - "bootstrap": "init", - "swim": { "disabled": True } - } - ], "mona": [ { "name": "my_mona", @@ -293,44 +286,6 @@ def test_dependency_on_abt_io(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) - def test_dependency_on_ssg(self): - providers = self.server.providers - self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "ssg", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong dependency - client_params["dependencies"] = {"dep1": "my_ssg_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_ssg"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - - # Try creating a provider without the required dependency - provider_params = self.make_provider_params([ - {"name": "dep1", "type": "ssg", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong dependency - provider_params["dependencies"] = {"dep1": "my_ssg_bad"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the required dependency - provider_params["dependencies"] = {"dep1": "my_ssg"} - providers.create(**provider_params) - self.assertEqual(len(providers), 3) - def test_dependency_on_mona(self): providers = self.server.providers self.assertEqual(len(providers), 2) @@ -599,59 +554,6 @@ def test_dependency_on_ph_with_id_and_rank(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) - def test_dependency_on_ph_with_ssg(self): - providers = self.server.providers - self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Get the address of this process to use instead of "local" - address = "ssg://my_ssg/0" - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong group - client_params["dependencies"] = {"dep1": "module_a:1@ssg://wrong_group/0"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong rank - client_params["dependencies"] = {"dep1": "module_a:1@ssg://my_ssg/123"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": f"module_a:1@{address}"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - - # Try creating a provider without the required dependency - provider_params = self.make_provider_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong group - provider_params["dependencies"] = {"dep1": "module_a:1@ssg://wrong_group/0"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong rank - provider_params["dependencies"] = {"dep1": "module_a:1@ssg://my_ssg/123"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the required dependency - provider_params["dependencies"] = {"dep1": f"module_a:1@{address}"} - providers.create(**provider_params) - self.assertEqual(len(providers), 3) - if __name__ == '__main__': unittest.main() diff --git a/python/mochi/bedrock/test_server.py b/python/mochi/bedrock/test_server.py index a3ec79c..14ded06 100644 --- a/python/mochi/bedrock/test_server.py +++ b/python/mochi/bedrock/test_server.py @@ -36,7 +36,7 @@ def test_server_config(self): server = mbs.Server(address="na+sm") config = server.config self.assertIsInstance(config, dict) - for expected_key in ["margo", "abt_io", "ssg", "bedrock", "providers", "clients", "libraries", "mona"]: + for expected_key in ["margo", "abt_io", "bedrock", "providers", "clients", "libraries", "mona"]: self.assertIn(expected_key, config) server.finalize() diff --git a/python/mochi/bedrock/test_service_group_handle.py b/python/mochi/bedrock/test_service_group_handle.py index b8f5448..a7992da 100644 --- a/python/mochi/bedrock/test_service_group_handle.py +++ b/python/mochi/bedrock/test_service_group_handle.py @@ -10,12 +10,22 @@ class TestServiceGroupHandleInit(unittest.TestCase): def setUp(self): self.tempdir = tempfile.TemporaryDirectory() - self.groupfile = os.path.join(self.tempdir.name, "group.ssg") + self.groupfile = os.path.join(self.tempdir.name, "group.flock") config = { - "ssg": [{ + "libraries": { + "flock": "libflock-bedrock-module.so" + }, + "providers": [{ "name": "my_group", - "bootstrap": "init", - "group_file": self.groupfile + "type": "flock", + "provider_id" : 1, + "config": { + "bootstrap": "self", + "file": self.groupfile, + "group": { + "type": "static" + } + } }] } self.server = mbs.Server(address="na+sm", config=config) @@ -27,44 +37,41 @@ def tearDown(self): self.server.finalize() del self.server - def test_make_service_group_handle_from_file(self): - """ - Note: because the server and client are on the same process, - trying to open the group file will lead to an SSG error - about the group ID already existing. - """ - # sgh = self.client.make_service_group_handle(self.groupfile) - # self.assertIsInstance(sgh, mbc.ServiceGroupHandle) - - def test_make_service_group_handle_from_gid(self): - ssg_group = self.server.ssg["my_group"] - gid = ssg_group.handle - sgh = self.client.make_service_group_handle_from_ssg(gid) - self.assertIsInstance(sgh, mbc.ServiceGroupHandle) - sgh.refresh() # just to get code coverage - def test_make_service_group_handle_from_address(self): address = str(self.server.margo.engine.address) sgh = self.client.make_service_group_handle([address]) self.assertIsInstance(sgh, mbc.ServiceGroupHandle) + def test_make_service_group_handle_from_file(self): + sgh = self.client.make_service_group_handle_from_flock(self.groupfile) + self.assertIsInstance(sgh, mbc.ServiceGroupHandle) + class TestServiceGroupHandle(unittest.TestCase): def setUp(self): self.tempdir = tempfile.TemporaryDirectory() - self.groupfile = os.path.join(self.tempdir.name, "group.ssg") + self.groupfile = os.path.join(self.tempdir.name, "group.flock") config = { - "ssg": [{ + "libraries": { + "flock": "libflock-bedrock-module.so" + }, + "providers": [{ "name": "my_group", - "bootstrap": "init", - "group_file": self.groupfile + "type": "flock", + "provider_id" : 1, + "config": { + "bootstrap": "self", + "file": self.groupfile, + "group": { + "type": "static" + } + } }] } self.server = mbs.Server(address="na+sm", config=config) self.client = mbc.Client(self.server.margo.engine) - self.sgh = self.client.make_service_group_handle_from_ssg( - self.server.ssg["my_group"].handle) + self.sgh = self.client.make_service_group_handle_from_flock(self.groupfile) def tearDown(self): del self.sgh @@ -88,7 +95,7 @@ def test_config(self): self.assertEqual(len(config.keys()), 1) self_address = str(self.server.margo.engine.address) self.assertIn(self_address, config) - for k in ["margo", "providers", "clients", "ssg", "abt_io", "bedrock"]: + for k in ["margo", "providers", "bedrock"]: self.assertIn(k, config[self_address]) def test_spec(self): diff --git a/python/mochi/bedrock/test_service_handle.py b/python/mochi/bedrock/test_service_handle.py index 2bcfd40..6b2588c 100644 --- a/python/mochi/bedrock/test_service_handle.py +++ b/python/mochi/bedrock/test_service_handle.py @@ -52,7 +52,7 @@ def test_client(self): def test_config(self): config = self.sh.config self.assertIsInstance(config, dict) - for k in ["margo", "providers", "clients", "ssg", "abt_io", "bedrock"]: + for k in ["margo", "providers", "clients", "abt_io", "bedrock"]: self.assertIn(k, config) def test_spec(self): @@ -180,43 +180,6 @@ def test_remove_xstream(self): with self.assertRaises(mbc.ClientException): self.server.margo.xstreams["my_xstream"] - def test_add_ssg_group_from_dict(self): - group_config = { - "name": "my_group", - "pool": "__primary__", - "bootstrap": "init", - "swim": { - "disabled": True - } - } - self.sh.add_ssg_group(group_config) - group = self.server.ssg["my_group"] - self.assertIsInstance(group, mbs.SSGGroup) - - def test_add_ssg_group_from_str(self): - group_config = { - "name": "my_group", - "pool": "__primary__", - "bootstrap": "init", - "swim": { - "disabled": True - } - } - self.sh.add_ssg_group(json.dumps(group_config)) - group = self.server.ssg["my_group"] - self.assertIsInstance(group, mbs.SSGGroup) - - def test_add_ssg_group_from_spec(self): - group_config = spec.SSGSpec( - name="my_group", - pool=spec.PoolSpec(name="__primary__", kind="fifo_wait", access="mpmc"), - bootstrap="init", - swim=spec.SwimSpec(disabled=True) - ) - self.sh.add_ssg_group(group_config) - group = self.server.ssg["my_group"] - self.assertIsInstance(group, mbs.SSGGroup) - def test_add_abtio_instance_from_dict(self): abtio_config = { "name": "my_abtio", diff --git a/python/mochi/bedrock/test_ssg_manager.py b/python/mochi/bedrock/test_ssg_manager.py deleted file mode 100644 index 98d2ea7..0000000 --- a/python/mochi/bedrock/test_ssg_manager.py +++ /dev/null @@ -1,99 +0,0 @@ -import unittest -import pymargo.logging -import mochi.bedrock.server as mbs -import mochi.bedrock.spec as spec - - -class TestSSGManager(unittest.TestCase): - - def setUp(self): - config = { - "ssg": [ - { - "name": "my_group", - "pool": "__primary__", - "bootstrap": "init", - "config": {}, - "swim": {} - } - ], - "libraries": { - "module_a": "./libModuleA.so" - }, - "providers": [ - { - "name": "my_provider_A1", - "type": "module_a", - "provider_id": 1, - "__if__": "$__ssg__.my_group.rank == 0" - }, - { - "name": "my_provider_A2", - "type": "module_a", - "provider_id": 2, - "__if__": "$__ssg__.my_group.rank == 1" - } - ] - } - self.server = mbs.Server(address="na+sm", config=config) - self.server.margo.engine.logger.set_log_level(pymargo.logging.level.critical) - - def tearDown(self): - self.server.finalize() - del self.server - - def test_get_ssg_manager(self): - ssg = self.server.ssg - self.assertIsInstance(ssg, mbs.SSGManager) - self.assertEqual(len(ssg), 1) - self.assertIn("my_group", ssg) - self.assertNotIn("not_my_group", ssg) - ssg_A = ssg[0] - ssg_B = ssg["my_group"] - self.assertEqual(ssg_A.name, ssg_B.name) - self.assertEqual(ssg_A.type, ssg_B.type) - self.assertEqual(ssg_A.handle, ssg_B.handle) - with self.assertRaises(mbs.BedrockException): - ssg[1] - with self.assertRaises(mbs.BedrockException): - ssg["bla"] - self.assertIn("my_provider_A1", self.server.providers) - self.assertNotIn("my_provider_A2", self.server.providers) - - - def test_ssg_manager_config(self): - config = self.server.ssg.config - self.assertIsInstance(config, list) - self.assertEqual(len(config), 1) - ssg_1 = config[0] - self.assertIsInstance(ssg_1, dict) - for key in ["name", "pool", "credential", "bootstrap", "group_file", "swim"]: - self.assertIn(key, ssg_1) - - def test_ssg_manager_spec(self): - spec_list = self.server.ssg.spec - self.assertIsInstance(spec_list, list) - for s in spec_list: - self.assertIsInstance(s, spec.SSGSpec) - - def test_add_ssg_group(self): - ssg = self.server.ssg - ssg.create( - name="my_group_2", - pool="__primary__") - self.assertEqual(len(ssg), 2) - ssg_A = ssg[1] - ssg_B = ssg["my_group_2"] - self.assertEqual(ssg_A.name, ssg_B.name) - self.assertEqual(ssg_A.type, ssg_B.type) - self.assertEqual(ssg_A.handle, ssg_B.handle) - - def test_resolve(self): - ssg = self.server.ssg - addr = ssg.resolve("ssg://my_group/0") - self.assertIsInstance(addr, pymargo.core.Address) - self.assertEqual(addr, self.server.margo.engine.address) - - -if __name__ == '__main__': - unittest.main() diff --git a/python/src/py-bedrock-client.cpp b/python/src/py-bedrock-client.cpp index d82499c..ffef4fe 100644 --- a/python/src/py-bedrock-client.cpp +++ b/python/src/py-bedrock-client.cpp @@ -35,15 +35,6 @@ PYBIND11_MODULE(pybedrock_client, m) { "Create a ServiceHandle instance", "address"_a, "provider_id"_a=0) - .def("make_service_group_handle_from_ssg_file", - [](const Client& client, - const std::string& groupfile, - uint16_t provider_id) { - return client.makeServiceGroupHandleFromSSGFile(groupfile, provider_id); - }, - "Create a ServiceGroupHandle instance", - "group_file"_a, - "provider_id"_a=0) .def("make_service_group_handle", [](const Client& client, const std::vector& addresses, @@ -53,15 +44,6 @@ PYBIND11_MODULE(pybedrock_client, m) { "Create a ServiceGroupHandle instance", "addresses"_a, "provider_id"_a=0) - .def("make_service_group_handle_from_ssg_group", - [](const Client& client, - uint64_t gid, - uint16_t provider_id) { - return client.makeServiceGroupHandleFromSSGGroup(gid, provider_id); - }, - "Create a ServiceGroupHandle instance", - "group_id"_a, - "provider_id"_a=0) .def("make_service_group_handle_from_flock_file", [](const Client& client, const std::string& groupfile, @@ -120,10 +102,6 @@ PYBIND11_MODULE(pybedrock_client, m) { const std::string& description) { sh.addABTioInstance(description); }, "description"_a = std::string("{}")) - .def("add_ssg_group", [](const ServiceHandle& sh, const std::string& config) { - sh.addSSGgroup(config); - }, - "description"_a) .def("add_pool", [](const ServiceHandle& sh, const std::string& config) { sh.addPool(config); }, diff --git a/python/src/py-bedrock-server.cpp b/python/src/py-bedrock-server.cpp index 6fe2ee3..637e340 100644 --- a/python/src/py-bedrock-server.cpp +++ b/python/src/py-bedrock-server.cpp @@ -8,9 +8,6 @@ #include "pybind11_json/pybind11_json.hpp" #include #include -#ifdef ENABLE_SSG - #include -#endif namespace py11 = pybind11; using namespace pybind11::literals; @@ -93,10 +90,6 @@ PYBIND11_MODULE(pybedrock_server, m) { [](std::shared_ptr server) { return server->getClientManager(); }) - .def_property_readonly("ssg_manager", - [](std::shared_ptr server) { - return server->getSSGManager(); - }) ; py11::class_ (m, "MargoManager") @@ -137,49 +130,6 @@ PYBIND11_MODULE(pybedrock_server, m) { .def_property_readonly("num_xstreams", &MargoManager::getNumXstreams) ; - py11::class_ (m, "SSGManager") - .def_property_readonly("config", [](const SSGManager& manager) { - return manager.getCurrentConfig().dump(); - }) - .def_property_readonly("num_groups", &SSGManager::getNumGroups) - .def("get_group", [](const SSGManager& ssg, const std::string& name) { - return ssg.getGroup(name); - }, "name_a") - .def("get_group", [](const SSGManager& ssg, size_t index) { - return ssg.getGroup(index); - }, "index_a") - .def("add_group", - [](SSGManager& ssg, - const std::string& name, - const py11::dict& config, - const std::shared_ptr& pool, - const std::string& bootstrap_method, - const std::string& group_file, - int64_t credential) { -#ifdef ENABLE_SSG - ssg_group_config_t cfg = SSG_GROUP_CONFIG_INITIALIZER; - cfg.ssg_credential = credential; -#define GET_SSG_FIELD(__field__) do { \ - if(config.contains(#__field__)) \ - cfg.swim_##__field__ = config[#__field__].cast(); \ - } while(0) - GET_SSG_FIELD(period_length_ms); - GET_SSG_FIELD(suspect_timeout_periods); - GET_SSG_FIELD(subgroup_member_count); - GET_SSG_FIELD(disabled); -#undef GET_SSG_FIELD - return ssg.addGroup(name, cfg, pool, bootstrap_method, group_file); -#else - throw Exception{"Bedrock was not compiled with SSG support"}; -#endif - }, "name"_a, "swim"_a=py11::dict{}, - "pool"_a=nullptr, "bootstrap"_a="init", - "group_file"_a="", "credential"_a=-1) - .def("resolve_address", [](const SSGManager& ssg, const std::string& address) { - return ADDR2CAPSULE(ssg.resolveAddress(address)); - }, "address"_a) - ; - py11::class_ (m, "ABTioManager") .def_property_readonly("config", [](const ABTioManager& manager) { return manager.getCurrentConfig().dump(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f52a303..31249d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,6 @@ set (server-src-files ABTioManager.cpp MargoManager.cpp MonaManager.cpp - SSGManager.cpp ProviderManager.cpp ClientManager.cpp DependencyFinder.cpp @@ -48,7 +47,6 @@ target_link_libraries (bedrock-server fmt::fmt ${OPTIONAL_ABT_IO} ${OPTIONAL_MONA} - ${OPTIONAL_SSG} ${OPTIONAL_MPI}) target_include_directories (bedrock-server PUBLIC $) target_include_directories (bedrock-server BEFORE PUBLIC @@ -65,7 +63,6 @@ add_library (bedrock::client ALIAS bedrock-client) target_compile_options (bedrock-client PUBLIC -Wall -Wextra -Wpedantic) target_link_libraries (bedrock-client PRIVATE coverage_config - ${OPTIONAL_SSG} ${OPTIONAL_FLOCK} PUBLIC thallium diff --git a/src/Client.cpp b/src/Client.cpp index 8ff7a49..fe558e9 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -14,9 +14,6 @@ #include "ServiceGroupHandleImpl.hpp" #include -#ifdef ENABLE_SSG -#include -#endif namespace tl = thallium; @@ -59,24 +56,6 @@ ServiceHandle Client::makeServiceHandle(const std::string& address, return ServiceHandle(service_impl); } -ServiceGroupHandle Client::makeServiceGroupHandleFromSSGFile( - const std::string& groupfile, - uint16_t provider_id) const { - auto impl = ServiceGroupHandleImpl::FromSSGfile(self, groupfile, provider_id); - auto result = ServiceGroupHandle{std::move(impl)}; - result.refresh(); - return result; -} - -ServiceGroupHandle Client::makeServiceGroupHandleFromSSGGroup( - uint64_t gid, - uint16_t provider_id) const { - auto impl = ServiceGroupHandleImpl::FromSSGid(self, gid, provider_id); - auto result = ServiceGroupHandle{std::move(impl)}; - result.refresh(); - return result; -} - ServiceGroupHandle Client::makeServiceGroupHandleFromFlockFile( const std::string& groupfile, uint16_t provider_id) const { diff --git a/src/ClientImpl.hpp b/src/ClientImpl.hpp index 84577a0..f51a068 100644 --- a/src/ClientImpl.hpp +++ b/src/ClientImpl.hpp @@ -27,7 +27,6 @@ class ClientImpl { tl::remote_procedure m_restore_provider; tl::remote_procedure m_add_client; tl::remote_procedure m_add_abtio; - tl::remote_procedure m_add_ssg_group; tl::remote_procedure m_add_pool; tl::remote_procedure m_add_xstream; tl::remote_procedure m_remove_pool; @@ -44,7 +43,6 @@ class ClientImpl { m_restore_provider(m_engine.define("bedrock_restore_provider")), m_add_client(m_engine.define("bedrock_add_client")), m_add_abtio(m_engine.define("bedrock_add_abtio")), - m_add_ssg_group(m_engine.define("bedrock_add_ssg_group")), m_add_pool(m_engine.define("bedrock_add_pool")), m_add_xstream(m_engine.define("bedrock_add_xstream")), m_remove_pool(m_engine.define("bedrock_remove_pool")), diff --git a/src/DependencyFinder.cpp b/src/DependencyFinder.cpp index 8c1f8fd..c3e83df 100644 --- a/src/DependencyFinder.cpp +++ b/src/DependencyFinder.cpp @@ -19,7 +19,6 @@ namespace bedrock { DependencyFinder::DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, const ABTioManager& abtio, - const SSGManager& ssg, const MonaManager& mona, const ProviderManager& pmanager, const ClientManager& cmanager) @@ -27,7 +26,6 @@ DependencyFinder::DependencyFinder(const MPIEnv& mpi, self->m_mpi = mpi.self; self->m_margo_context = margo; self->m_abtio_context = abtio.self; - self->m_ssg_context = ssg.self; self->m_mona_context = mona.self; self->m_provider_manager = pmanager.self; self->m_client_manager = cmanager.self; @@ -97,19 +95,6 @@ std::shared_ptr DependencyFinder::find( if (resolved) { *resolved = spec; } return mona_id; - } else if (type == "ssg") { // SSG group - - auto ssg_manager_impl = self->m_ssg_context.lock(); - if (!ssg_manager_impl) { - throw Exception("Could not resolve SSG dependency: no SSGManager found"); - } - auto group = SSGManager(ssg_manager_impl).getGroup(spec); - if (!group) { - throw Exception("Could not find SSG group with name \"{}\"", spec); - } - if (resolved) { *resolved = spec; } - return group; - } else if (kind == BEDROCK_KIND_CLIENT) { auto client = findClient(type, spec); @@ -293,31 +278,12 @@ DependencyFinder::makeProviderHandle(const std::string& client_name, } else { - if (locator.rfind("ssg://", 0) == 0) { - auto ssg_manager_impl = self->m_ssg_context.lock(); - if (!ssg_manager_impl) { - throw Exception( - "Could not resolve SSG address: no SSGManager found"); - } - hg_addr_t ssg_addr - = SSGManager(ssg_manager_impl).resolveAddress(locator); - hg_return_t hret = margo_addr_dup(mid, ssg_addr, &addr); - if (hret != HG_SUCCESS) { - throw Exception( - "Failed to duplicate address returned by " - "SSGManager (margo_addr_dup returned {})", - std::to_string(hret)); - } - - } else { - - hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); - if (hret != HG_SUCCESS) { - throw Exception( + hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); + if (hret != HG_SUCCESS) { + throw Exception( "Failed to lookup address {} " "(margo_addr_lookup returned {})", locator, std::to_string(hret)); - } } ProviderDescriptor descriptor; @@ -414,30 +380,12 @@ DependencyFinder::makeProviderHandle(const std::string& client_name, } else { - if (locator.rfind("ssg://", 0) == 0) { - auto ssg_manager_impl = self->m_ssg_context.lock(); - if (!ssg_manager_impl) { - throw Exception("Could not resolve SSG address: no SSGManager found"); - } - hg_addr_t ssg_addr - = SSGManager(ssg_manager_impl).resolveAddress(locator); - hg_return_t hret = margo_addr_dup(mid, ssg_addr, &addr); - if (hret != HG_SUCCESS) { - throw Exception( - "Failed to duplicate address returned by " - "SSGManager (margo_addr_dup returned {})", - std::to_string(hret)); - } - - } else { - - hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); - if (hret != HG_SUCCESS) { - throw Exception( + hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); + if (hret != HG_SUCCESS) { + throw Exception( "Failed to lookup address {} " "(margo_addr_lookup returned {})", locator, std::to_string(hret)); - } } try { diff --git a/src/DependencyFinderImpl.hpp b/src/DependencyFinderImpl.hpp index dd3f088..402f55a 100644 --- a/src/DependencyFinderImpl.hpp +++ b/src/DependencyFinderImpl.hpp @@ -9,7 +9,6 @@ #include "MargoManagerImpl.hpp" #include "ABTioManagerImpl.hpp" #include "MonaManagerImpl.hpp" -#include "SSGManagerImpl.hpp" #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "Formatting.hpp" @@ -34,7 +33,6 @@ class DependencyFinderImpl { std::shared_ptr m_mpi; std::shared_ptr m_margo_context; std::weak_ptr m_abtio_context; - std::weak_ptr m_ssg_context; std::weak_ptr m_mona_context; std::weak_ptr m_provider_manager; std::weak_ptr m_client_manager; diff --git a/src/SSGManager.cpp b/src/SSGManager.cpp deleted file mode 100644 index b3b4ba3..0000000 --- a/src/SSGManager.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#include -#include -#include -#include "JsonUtil.hpp" -#include "SSGManagerImpl.hpp" -#include -#include -#include -#ifdef ENABLE_SSG - #include - #ifdef ENABLE_MPI - #include - #endif - #ifdef ENABLE_PMIX - #include - #endif -#endif -#include -#include - -namespace bedrock { - -using nlohmann::json; -using namespace std::string_literals; - -int SSGManagerImpl::s_num_ssg_init = 0; -#ifdef ENABLE_PMIX -bool SSGManagerImpl::s_initialized_pmix = false; -#endif - -class SSGUpdateHandler { -#ifdef ENABLE_SSG - public: - static void membershipUpdate(void* group_data, ssg_member_id_t member_id, - ssg_member_update_type_t update_type); -#endif -}; - -SSGManager::SSGManager(const MargoManager& margo, - const Jx9Manager& jx9, - const json& config) -: self(std::make_shared()) { - self->m_margo_manager = margo; - self->m_jx9_manager = jx9; - - if(config.is_null()) return; - if(!(config.is_array() || config.is_object())) - throw BEDROCK_DETAILED_EXCEPTION("\"ssg\" field must be an object or an array"); - -#ifndef ENABLE_SSG - if (!config.empty()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Configuration has \"ssg\" entry but Bedrock wasn't compiled with SSG support"); - } -#else - if (config.is_object()) { - addGroupFromJSON(config); - } else if (config.is_array()) { - for (const auto& c : config) { - addGroupFromJSON(c); - } - } - - self->updateJx9Ranks(); -#endif -} - -// LCOV_EXCL_START - -SSGManager::SSGManager(const SSGManager&) = default; - -SSGManager::SSGManager(SSGManager&&) = default; - -SSGManager& SSGManager::operator=(const SSGManager&) = default; - -SSGManager& SSGManager::operator=(SSGManager&&) = default; - -SSGManager::~SSGManager() = default; - -SSGManager::operator bool() const { return static_cast(self); } - -// LCOV_EXCL_STOP - -std::shared_ptr SSGManager::getGroup(const std::string& group_name) const { -#ifdef ENABLE_SSG - auto it = std::find_if(self->m_ssg_groups.begin(), self->m_ssg_groups.end(), - [&](auto& g) { return g->getName() == group_name; }); - if (it == self->m_ssg_groups.end()) { - throw BEDROCK_DETAILED_EXCEPTION("Could not find SSG group with name \"{}\"", group_name); - return nullptr; - } else { - return *it; - } -#else - (void)group_name; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiler with SSG support"); - return nullptr; -#endif -} - -std::shared_ptr SSGManager::getGroup(size_t group_index) const { -#ifdef ENABLE_SSG - if(group_index >= self->m_ssg_groups.size()) { - throw BEDROCK_DETAILED_EXCEPTION("Could not find SSG group at index {}", group_index); - return nullptr; - } - return self->m_ssg_groups[group_index]; -#else - (void)group_index; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiler with SSG support"); - return nullptr; -#endif -} - -size_t SSGManager::getNumGroups() const { -#ifdef ENABLE_SSG - return self->m_ssg_groups.size(); -#else - return 0; -#endif -} - -std::shared_ptr -SSGManager::addGroup(const std::string& name, - const ssg_group_config_t& config, - const std::shared_ptr& pool, - const std::string& bootstrap, - const std::string& group_file) { -#ifndef ENABLE_SSG - (void)name; - (void)config; - (void)pool; - (void)bootstrap; - (void)group_file; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock wasn't compiled with SSG support"); - return nullptr; -#else // ENABLE_SSG - int ret; - ssg_group_id_t gid = SSG_GROUP_ID_INVALID; - auto margo = MargoManager(self->m_margo_manager); - auto mid = margo.getMargoInstance(); - - auto it = std::find_if(self->m_ssg_groups.begin(), self->m_ssg_groups.end(), - [&](auto& g) { return g->getName() == name; }); - if (it != self->m_ssg_groups.end()) { - throw BEDROCK_DETAILED_EXCEPTION("SSG group name \"{}\" already used", name); - } - - if (SSGManagerImpl::s_num_ssg_init == 0) { - int ret = ssg_init(); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not initialize SSG (ssg_init returned {})", ret); - } - } - SSGManagerImpl::s_num_ssg_init += 1; - - // The inner data of the ssg_entry will be set later. - // The ssg_entry needs to be created here because the - // membership callback needs it. - auto ssg_entry = std::make_shared(self, name, pool); - - spdlog::trace("Creating SSG group {} with bootstrap method {}", name, - bootstrap); - - (void)pool; // TODO add support for specifying the pool - - auto method = bootstrap; - - if (method == "init|join" - || method == "mpi|join" - || method == "pmix|join") { - auto sep = method.find('|'); - if(group_file.empty()) { - auto new_method = method.substr(0, sep); - spdlog::trace("Group file not specified, changing bootstrap method from \"{}\" to \"{}\"", - method, new_method); - method = std::move(new_method); - } else { - std::ifstream f(group_file.c_str()); - if(f.good()) { - auto new_method = method.substr(sep+1); - spdlog::trace("File {} found, changing bootstrap method from \"{}\" to \"{}\"", - group_file, method, new_method); - method = std::move(new_method); - } else { - auto new_method = method.substr(0, sep); - spdlog::trace("File {} not found, changing bootstrap method from \"{}\" to \"{}\"", - group_file, method, new_method); - method = std::move(new_method); - } - } - } - - if (method == "init") { - - std::string addr_str = margo.getThalliumEngine().self(); - std::vector addresses = {addr_str.c_str()}; - - ret = ssg_group_create(mid, name.c_str(), addresses.data(), 1, - const_cast(&config), - SSGUpdateHandler::membershipUpdate, ssg_entry.get(), - &gid); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("ssg_group_create failed with error code {}", ret); - } - - } else if (method == "join") { - - if (group_file.empty()) { - throw BEDROCK_DETAILED_EXCEPTION( - "SSG \"join\" bootstrapping mode requires a group file to be " - "specified"); - } - int num_addrs = 32; // XXX make that configurable? - ret = ssg_group_id_load(group_file.c_str(), &num_addrs, &gid); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Failed to load SSG group from file {}" - " (ssg_group_id_load returned {}", - group_file, ret); - } - ret = ssg_group_join(mid, gid, SSGUpdateHandler::membershipUpdate, ssg_entry.get()); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Failed to join SSG group {} " - "(ssg_group_join returned {})", - name, ret); - } - - } else if (method == "mpi") { -#ifdef ENABLE_MPI - ret = ssg_group_create_mpi( - mid, name.c_str(), MPI_COMM_WORLD, - const_cast(&config), - SSGUpdateHandler::membershipUpdate, ssg_entry.get(), &gid); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Failed to create SSG group {} " - "(ssg_group_create_mpi returned {})", - name, ret); - } -#else // ENABLE_MPI - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiled with MPI support"); -#endif // ENABLE_MPI - - } else if (method == "pmix") { -#ifdef ENABLE_PMIX - pmix_proc_t proc; - auto ret = PMIx_Init(&proc, NULL, 0); - if (ret != PMIX_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("Could not initialize PMIx (PMIx_Init returned {})", - ret); - } - gid = ssg_group_create_pmix( - mid, name.c_str(), proc, - const_cast(config), - SSGUpdateHandler::membershipUpdate, group_data.get()); -#else // ENABLE_PMIX - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiled with PMIx support"); -#endif // ENABLE_PMIX - } else { - throw BEDROCK_DETAILED_EXCEPTION("Invalid SSG bootstrapping method {}", bootstrap); - } - int rank = -1; - ret = ssg_get_group_self_rank(gid, &rank); - if (rank == -1 || ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("Could not get SSG group rank from group {}", name); - } - if (!group_file.empty() && (rank == 0) - && (method == "init" || method == "mpi" - || method == "pmix")) { - ret = ssg_group_id_store(group_file.c_str(), gid, SSG_ALL_MEMBERS); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not write SSG group file {}" - " (ssg_group_id_store return {}", - group_file, ret); - } - } - ssg_entry->setSSGid(gid); - ssg_entry->config = config; - ssg_entry->bootstrap = bootstrap; - ssg_entry->group_file = group_file; - ssg_entry->pool = pool; - ssg_entry->rank = rank; - self->m_ssg_groups.push_back(std::move(ssg_entry)); - - self->updateJx9Ranks(); - - return ssg_entry; -#endif // ENABLE_SSSG -} - -std::shared_ptr -SSGManager::addGroupFromJSON(const json& description) { -#ifndef ENABLE_SSG - (void)description; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock wasn't compiled with SSG support"); - return 0; -#else // ENABLE_SSG - - static json const configSchema = R"( - { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "name": {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - "pool": {"oneOf": [ - {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - {"type": "integer", "minimum": 0 } - ]}, - "credential": {"type": "integer"}, - "group_file": {"type": "string"}, - "bootstrap": {"enum": ["init", "mpi", "pmix", "join", "init|join", "mpi|join", "pmix|join"]}, - "swim": { - "type": "object", - "properties": { - "period_length_ms": {"type": "integer"}, - "suspect_timeout_periods": {"type": "integer"}, - "subgroup_member_count": {"type": "integer"}, - "disabled": {"type": "boolean"} - } - } - }, - "required": ["name"] - } - )"_json; - static const JsonValidator validator{configSchema}; - validator.validate(description, "SSGManager"); - auto name = description["name"].get(); - std::shared_ptr pool; - if(description.contains("pool") && description["pool"].is_number()) { - pool = MargoManager(self->m_margo_manager) - .getPool(description["pool"].get()); - } else { - pool = MargoManager(self->m_margo_manager) - .getPool(description.value("pool", "__primary__")); - } - auto bootstrap = description.value("bootstrap", "init"); - auto group_file = description.value("group_file", ""); - ssg_group_config_t config = SSG_GROUP_CONFIG_INITIALIZER; - if(description.contains("credential")) - config.ssg_credential = description["credential"].get(); - if(description.contains("swim") && !description["swim"].value("disabled", false)) { - auto& swim = description["swim"]; - config.swim_disabled = 0; - config.swim_period_length_ms = swim.value("period_length_ms", 0); - config.swim_suspect_timeout_periods = swim.value("suspect_timeout_periods", -1); - config.swim_subgroup_member_count = swim.value("subgroup_member_count", -1); - } else { - config.swim_disabled = 1; - } - return addGroup(name, config, pool, bootstrap, group_file); -#endif // ENABLE_SSG -} - -#ifdef ENABLE_SSG -void SSGUpdateHandler::membershipUpdate(void* group_data, ssg_member_id_t member_id, - ssg_member_update_type_t update_type) { - SSGEntry* gdata = reinterpret_cast(group_data); - (void)gdata; - spdlog::trace("SSG membership updated: member_id={}, update_type={}", - member_id, std::to_string(update_type)); - int self_rank; - ssg_get_group_self_rank(gdata->getHandle(), &self_rank); - gdata->rank = (uint64_t)self_rank; - auto manager = gdata->owner.lock(); - if(manager) manager->updateJx9Ranks(); -} -#endif - -hg_addr_t SSGManager::resolveAddress(const std::string& address) const { -#ifndef ENABLE_SSG - (void)address; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock wasn't compiled with SSG support"); -#else // ENABLE_SSG - std::regex re("ssg:\\/\\/([a-zA-Z_][a-zA-Z0-9_]*)\\/(#?)([0-9][0-9]*)$"); - std::smatch match; - if (std::regex_search(address, match, re)) { - auto group_name = match.str(1); - auto is_member_id = match.str(2) == "#"; - auto member_id_or_rank = atol(match.str(3).c_str()); - auto ssg_entry = getGroup(group_name); - if (!ssg_entry) { - throw BEDROCK_DETAILED_EXCEPTION("Could not resolve \"{}\" to a valid SSG group", - group_name); - } - ssg_member_id_t member_id; - auto gid = ssg_entry->getHandle(); - if (!is_member_id) { - int ret = ssg_get_group_member_id_from_rank(gid, member_id_or_rank, - &member_id); - if (member_id == SSG_MEMBER_ID_INVALID || ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("Invalid rank {} in group {}", - member_id_or_rank, group_name); - } - } else { - member_id = member_id_or_rank; - } - hg_addr_t addr = HG_ADDR_NULL; - int ret = ssg_get_group_member_addr(gid, member_id, &addr); - if (addr == HG_ADDR_NULL || ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("Invalid member id {} in group {}", member_id, - group_name); - } - return addr; - } else { - throw BEDROCK_DETAILED_EXCEPTION("Invalid SSG address specification \"{}\"", address); - } - return HG_ADDR_NULL; -#endif // ENABLE_SSG -} - -json SSGManager::getCurrentConfig() const { -#ifndef ENABLE_SSG - return json::array(); -#else - return self->makeConfig(); -#endif -} - -} // namespace bedrock diff --git a/src/SSGManagerImpl.hpp b/src/SSGManagerImpl.hpp deleted file mode 100644 index 252cc01..0000000 --- a/src/SSGManagerImpl.hpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_SSG_CONTEXT_IMPL_H -#define __BEDROCK_SSG_CONTEXT_IMPL_H - -#include -#include -#include -#include -#include -#include "MargoManagerImpl.hpp" -#include -#include -#include -#include - -#ifdef ENABLE_SSG -#include - -namespace std { - -static inline auto to_string(ssg_member_update_type_t t) -> std::string { - switch(t) { - case SSG_MEMBER_JOINED: return "SSG_MEMBER_JOINED"; - case SSG_MEMBER_LEFT: return "SSG_MEMBER_LEFT"; - case SSG_MEMBER_DIED: return "SSG_MEMBER_DIED"; - default: return "UNKNOWN"; - } -} - -} - -#endif - -namespace bedrock { - -class SSGManagerImpl; - -class SSGEntry : public NamedDependency { - - public: - -#ifdef ENABLE_SSG - ssg_group_config_t config; - std::string bootstrap; - std::string group_file; - std::shared_ptr pool; - std::weak_ptr owner; - - uint64_t rank; // current rank of the process in this group - - SSGEntry(std::shared_ptr o, std::string name, std::shared_ptr p) - : NamedDependency( - std::move(name), - "ssg", SSG_GROUP_ID_INVALID, - std::function()) - , pool{std::move(p)} - , owner(o) - {} - - SSGEntry(const SSGEntry&) = delete; - SSGEntry(SSGEntry&&) = delete; - - void setSSGid(ssg_group_id_t gid) { - m_handle = reinterpret_cast(gid); - } - - ssg_group_id_t getSSGid() const { - return reinterpret_cast(m_handle); - } - - json makeConfig() const { - json c = json::object(); - c["name"] = getName(); - c["bootstrap"] = bootstrap; - c["group_file"] = group_file; - c["pool"] = pool->getName(); - c["credential"] = config.ssg_credential; - if(!config.swim_disabled) { - c["swim"] = json::object(); - auto& swim = c["swim"]; - swim["period_length_ms"] = config.swim_period_length_ms; - swim["suspect_timeout_periods"] = config.swim_suspect_timeout_periods; - swim["subgroup_member_count"] = config.swim_subgroup_member_count; - } - return c; - } - -#else - - json makeConfig() const { - return json::object(); - } - -#endif -}; - -class SSGManagerImpl { - - public: - std::shared_ptr m_margo_manager; - std::shared_ptr m_jx9_manager; - std::vector> m_ssg_groups; - - json makeConfig() const { - auto config = json::array(); - for (const auto& g : m_ssg_groups) { - config.push_back(g->makeConfig()); - } - return config; - } - -#ifdef ENABLE_SSG - SSGManagerImpl() { - if (SSGManagerImpl::s_num_ssg_init == 0) { - int ret = ssg_init(); - if (ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION("Could not initialize SSG (ssg_init returned {})", - ret); - } - } - SSGManagerImpl::s_num_ssg_init += 1; - } - - static void releaseSSGid(ssg_group_id_t gid) { - if (!gid) return; - int ret = ssg_group_leave(gid); - // if SWIM is disabled, this function will return SSG_ERR_NOT_SUPPORTED - if (ret != SSG_SUCCESS && ret != SSG_ERR_NOT_SUPPORTED) { - spdlog::error( - "Could not leave SSG group (ssg_group_leave returned {})", - ret); - } - ret = ssg_group_destroy(gid); - if (ret != SSG_SUCCESS) { - spdlog::error( - "Could not destroy SSG group (ssg_group_destroy returned {})", - ret); - } - } - - ~SSGManagerImpl() { - spdlog::trace("Destroying SSGManager (count = {})", s_num_ssg_init); - m_ssg_groups.clear(); - s_num_ssg_init -= 1; - if (s_num_ssg_init == 0) { - spdlog::trace("Finalizing SSG"); - ssg_finalize(); - } - } - - void updateJx9Ranks() { - json rankMap = json::object(); - for(auto& g : m_ssg_groups) { - auto& x = rankMap[g->getName()] = json::object(); - x["rank"] = g->rank; - } - Jx9Manager(m_jx9_manager).setVariable( - "__ssg__", rankMap.dump()); - } -#endif - - void clear() { -#ifdef ENABLE_SSG - for(auto& g : m_ssg_groups) { - releaseSSGid(g->getHandle()); - } - m_ssg_groups.resize(0); -#endif - } - - - static int s_num_ssg_init; -#ifdef ENABLE_PMIX - static bool s_initialized_pmix; -#endif - -}; - -} // namespace bedrock - -#endif diff --git a/src/Server.cpp b/src/Server.cpp index de4b57b..3103114 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include "MargoLogging.hpp" @@ -139,13 +138,6 @@ Server::Server(const std::string& address, const std::string& configString, try { - // Initializing SSG context - spdlog::trace("Initializing SSGManager"); - auto& ssgConfig = config["ssg"]; - auto ssgMgr = SSGManager(margoMgr, jx9Manager, ssgConfig); - self->m_ssg_manager = ssgMgr; - spdlog::trace("SSGManager initialized"); - // Initialize abt-io context spdlog::trace("Initializing ABTioManager"); auto& abtioConfig = config["abt_io"]; @@ -183,7 +175,7 @@ Server::Server(const std::string& address, const std::string& configString, // Initializing dependency finder spdlog::trace("Initializing DependencyFinder"); auto dependencyFinder = DependencyFinder( - mpi, margoMgr, abtioMgr, ssgMgr, monaMgr, providerManager, clientManager); + mpi, margoMgr, abtioMgr, monaMgr, providerManager, clientManager); self->m_dependency_finder = dependencyFinder; self->m_dependency_finder->m_timeout = dependency_timeout; spdlog::trace("DependencyFinder initialized"); @@ -224,14 +216,10 @@ ClientManager Server::getClientManager() const { return self->m_client_manager; } -SSGManager Server::getSSGManager() const { return self->m_ssg_manager; } - void Server::onPreFinalize(void* uargs) { spdlog::trace("Calling Server's pre-finalize callback"); auto server = reinterpret_cast(uargs); if(server->self) { - if(server->self->m_ssg_manager) - server->self->m_ssg_manager->clear(); if(server->self->m_provider_manager) server->self->m_provider_manager.reset(); } diff --git a/src/ServerImpl.hpp b/src/ServerImpl.hpp index 44808d0..36f3752 100644 --- a/src/ServerImpl.hpp +++ b/src/ServerImpl.hpp @@ -12,7 +12,6 @@ #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "DependencyFinderImpl.hpp" -#include "SSGManagerImpl.hpp" #include "Jx9ManagerImpl.hpp" #include "MPIEnvImpl.hpp" #include "bedrock/Jx9Manager.hpp" @@ -36,7 +35,6 @@ class ServerImpl : public tl::provider { std::shared_ptr m_margo_manager; std::shared_ptr m_abtio_manager; std::shared_ptr m_mona_manager; - std::shared_ptr m_ssg_manager; std::shared_ptr m_client_manager; std::shared_ptr m_provider_manager; std::shared_ptr m_dependency_finder; @@ -46,7 +44,6 @@ class ServerImpl : public tl::provider { tl::remote_procedure m_get_config_rpc; tl::remote_procedure m_query_config_rpc; tl::remote_procedure m_add_abtio_rpc; - tl::remote_procedure m_add_ssg_group_rpc; tl::remote_procedure m_add_pool_rpc; tl::remote_procedure m_add_xstream_rpc; @@ -65,8 +62,6 @@ class ServerImpl : public tl::provider { define("bedrock_query_config", &ServerImpl::queryConfigRPC, m_tl_pool)), m_add_abtio_rpc( define("bedrock_add_abtio", &ServerImpl::addABTioRPC, m_tl_pool)), - m_add_ssg_group_rpc( - define("bedrock_add_ssg_group", &ServerImpl::addSSGgroupRPC, m_tl_pool)), m_add_pool_rpc( define("bedrock_add_pool", &ServerImpl::addPoolRPC, m_tl_pool)), m_add_xstream_rpc( @@ -81,7 +76,6 @@ class ServerImpl : public tl::provider { m_get_config_rpc.deregister(); m_query_config_rpc.deregister(); m_add_abtio_rpc.deregister(); - m_add_ssg_group_rpc.deregister(); m_add_pool_rpc.deregister(); m_add_xstream_rpc.deregister(); m_remove_pool_rpc.deregister(); @@ -94,7 +88,6 @@ class ServerImpl : public tl::provider { config["abt_io"] = m_abtio_manager->makeConfig(); config["clients"] = m_client_manager->makeConfig(); config["providers"] = m_provider_manager->makeConfig(); - config["ssg"] = m_ssg_manager->makeConfig(); config["mona"] = m_mona_manager->makeConfig(); config["libraries"] = json::parse(ModuleContext::getCurrentConfig()); config["bedrock"] = json::object(); @@ -136,18 +129,6 @@ class ServerImpl : public tl::provider { req.respond(result); } - void addSSGgroupRPC(const tl::request& req, const std::string& description) { - RequestResult result; - result.success() = true; - try { - SSGManager(m_ssg_manager).addGroupFromJSON(json::parse(description)); - } catch (const std::exception& ex) { - result.error() = ex.what(); - result.success() = false; - } - req.respond(result); - } - void addPoolRPC(const tl::request& req, const std::string& config) { RequestResult result; result.success() = true; diff --git a/src/ServiceGroupHandleImpl.hpp b/src/ServiceGroupHandleImpl.hpp index 69b0812..a9db3fb 100644 --- a/src/ServiceGroupHandleImpl.hpp +++ b/src/ServiceGroupHandleImpl.hpp @@ -11,9 +11,6 @@ #include "ClientImpl.hpp" #include "ServiceHandleImpl.hpp" #include "Formatting.hpp" -#ifdef ENABLE_SSG -#include -#endif #ifdef ENABLE_FLOCK #include #include @@ -31,10 +28,6 @@ class ServiceGroupHandleImpl { uint16_t m_provider_id; std::vector> m_shs; -#ifdef ENABLE_SSG - ssg_group_id_t m_gid = SSG_GROUP_ID_INVALID; - bool m_owns_gid = false; -#endif #ifdef ENABLE_FLOCK flock_client_t m_flock_client = FLOCK_CLIENT_NULL; flock_group_handle_t m_flock_gh = FLOCK_GROUP_HANDLE_NULL; @@ -47,10 +40,6 @@ class ServiceGroupHandleImpl { : m_client(std::move(client)), m_provider_id(provider_id) {} ~ServiceGroupHandleImpl() { -#ifdef ENABLE_SSG - if(m_owns_gid) - ssg_group_destroy(m_gid); -#endif #ifdef ENABLE_FLOCK if(m_flock_gh) flock_group_handle_release(m_flock_gh); if(m_flock_client) flock_client_finalize(m_flock_client); @@ -59,45 +48,6 @@ class ServiceGroupHandleImpl { std::vector queryAddresses(bool refresh) const { std::vector addresses; -#ifdef ENABLE_SSG - if(m_gid) { - auto mid = m_client->m_engine.get_margo_instance(); - int ret = SSG_SUCCESS; - if(refresh) - ret = ssg_group_refresh(mid, m_gid); - if (ret != SSG_SUCCESS) - throw BEDROCK_DETAILED_EXCEPTION( - "Could not refresh SSG group view " - "(ssg_group_refresh returned {})", ret); - int group_size = 0; - ret = ssg_get_group_size(m_gid, &group_size); - if (ret != SSG_SUCCESS) - throw BEDROCK_DETAILED_EXCEPTION( - "Could not get SSG group size " - "(ssg_get_group_size returned {})", ret); - addresses.reserve(group_size); - for (int i = 0; i < group_size; i++) { - ssg_member_id_t member_id = SSG_MEMBER_ID_INVALID; - ret = ssg_get_group_member_id_from_rank(m_gid, i, &member_id); - if (member_id == SSG_MEMBER_ID_INVALID || ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not get member ID from rank {} " - "(ssg_get_group_member_id_from_rank returned {})", - i, ret); - } - char* addr = NULL; - ret = ssg_get_group_member_addr_str(m_gid, member_id, &addr); - if (addr == NULL || ret != SSG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not get address from SSG member {} (rank {}) " - "(ssg_get_group_member_addr_str returned {})", member_id, - i, ret); - } - addresses.emplace_back(addr); - } - return addresses; - } -#endif #if ENABLE_FLOCK if(m_flock_gh) { flock_return_t ret = flock_group_access_view(m_flock_gh, @@ -119,46 +69,6 @@ class ServiceGroupHandleImpl { throw Exception{"ServiceGroupHandle not associated with an SSG or Flock group"}; } - static std::shared_ptr FromSSGfile( - std::shared_ptr client, - const std::string& groupfile, - uint16_t provider_id) { -#ifdef ENABLE_SSG - int num_addrs = SSG_ALL_MEMBERS; - ssg_group_id_t gid = SSG_GROUP_ID_INVALID; - int ret = ssg_group_id_load(groupfile.c_str(), &num_addrs, &gid); - if (ret != SSG_SUCCESS) - throw BEDROCK_DETAILED_EXCEPTION("Could not load group file {} " - "(ssg_group_id_load returned {})", groupfile, ret); - auto sg_impl = std::make_shared(std::move(client), provider_id); - sg_impl->m_gid = gid; - sg_impl->m_owns_gid = true; - return sg_impl; -#else - (void)client; - (void)groupfile; - (void)provider_id; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not built with SSG support"); -#endif - } - - static std::shared_ptr FromSSGid( - std::shared_ptr client, - uint64_t gid, - uint16_t provider_id) { -#ifdef ENABLE_SSG - std::vector addresses; - auto sg_impl = std::make_shared(client, provider_id); - sg_impl->m_gid = gid; - return sg_impl; -#else - (void)client; - (void)gid; - (void)provider_id; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not built with SSG support"); -#endif - } - static std::shared_ptr FromFlockFile( std::shared_ptr client, const std::string& groupfile, diff --git a/src/ServiceHandle.cpp b/src/ServiceHandle.cpp index 20290f5..18eaecb 100644 --- a/src/ServiceHandle.cpp +++ b/src/ServiceHandle.cpp @@ -170,14 +170,6 @@ void ServiceHandle::addABTioInstance(const std::string& description, SEND_RPC_WITH_BOOL_RESULT(description); } -void ServiceHandle::addSSGgroup(const std::string& config, - AsyncRequest* req) const { - if (not self) throw BEDROCK_DETAILED_EXCEPTION("Invalid bedrock::ServiceHandle object"); - auto& rpc = self->m_client->m_add_ssg_group; - auto& ph = self->m_ph; - SEND_RPC_WITH_BOOL_RESULT(config); -} - void ServiceHandle::addPool(const std::string& config, AsyncRequest* req) const { if (not self) throw BEDROCK_DETAILED_EXCEPTION("Invalid bedrock::ServiceHandle object"); diff --git a/src/bedrock-config.cmake.in b/src/bedrock-config.cmake.in index 3a01449..9c1791f 100644 --- a/src/bedrock-config.cmake.in +++ b/src/bedrock-config.cmake.in @@ -19,9 +19,6 @@ pkg_check_modules (MARGO REQUIRED IMPORTED_TARGET margo) if(@ENABLE_MPI@) find_dependency (MPI) endif() -if(@ENABLE_SSG@) - pkg_check_modules (SSG REQUIRED IMPORTED_TARGET ssg) -endif() if(@ENABLE_ABT_IO@) pkg_check_modules (ABTIO REQUIRED IMPORTED_TARGET abt-io) endif() diff --git a/tests/ValidConfigs.json b/tests/ValidConfigs.json index ef0e65b..75b588e 100644 --- a/tests/ValidConfigs.json +++ b/tests/ValidConfigs.json @@ -2,60 +2,48 @@ { "test": "empty configuration", "input": {}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"ssg":[],"mona":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"mona":[]} }, { "test": "using use_progress_thread and rpc_thread_count in Margo", "input": {"margo":{"use_progress_thread":true,"rpc_thread_count":2}}, - "output": {"abt_io":[],"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[],"ssg":[],"mona":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[],"mona":[]} }, { "test": "defining an ABT-IO instance", "input": {"abt_io":[{"name":"my_abt_io","pool":"__primary__"}]}, - "output": {"abt_io":[{"config":{"internal_pool_flag":false,"liburing_flags":[],"null_io_read":false,"null_io_write":false,"num_urings":0,"trace_io":false},"name":"my_abt_io","pool":"__primary__"}],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"ssg":[],"mona":[]} - }, - - { - "test": "defining an SSG group with mpi bootstrapping", - "input": {"ssg":[{"name":"my_ssg_group","bootstrap":"mpi"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"ssg":[{"bootstrap":"mpi","credential":-1,"group_file":"","name":"my_ssg_group","pool":"__primary__"}],"mona":[]} - }, - - { - "test": "defining an SSG group with init bootstrapping", - "input": {"ssg":[{"name":"my_ssg_group","bootstrap":"init"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"ssg":[{"bootstrap":"init","credential":-1,"group_file":"","name":"my_ssg_group","pool":"__primary__"}],"mona":[]} + "output": {"abt_io":[{"config":{"internal_pool_flag":false,"liburing_flags":[],"null_io_read":false,"null_io_write":false,"num_urings":0,"trace_io":false},"name":"my_abt_io","pool":"__primary__"}],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"mona":[]} }, { "test": "defining a Mona instance", "input": {"mona":[{"name":"my_mona", "pool":"__primary__"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[{"address":"","config":{},"name":"my_mona","pool":"__primary__"}],"providers":[],"ssg":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[{"address":"","config":{},"name":"my_mona","pool":"__primary__"}],"providers":[]} }, { "test": "load a module library", "input": {"libraries":{"module_a":"./libModuleA.so"}}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[],"ssg":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[]} }, { "test": "instantiate a provider from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}],"ssg":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a provider from module-a with simplified syntax", "input": {"libraries.module_a":"./libModuleA.so","providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}],"ssg":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a client from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"clients":[{"name":"my_client","type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[],"ssg":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[]} } ] From f34a8dde9d4f9489023c202f86ba014dde53a882 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Wed, 4 Sep 2024 10:32:22 +0100 Subject: [PATCH 02/10] removed SSG from spack.yaml files --- spack.yaml | 2 -- tests/spack.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/spack.yaml b/spack.yaml index 086be56..6a64708 100644 --- a/spack.yaml +++ b/spack.yaml @@ -6,7 +6,6 @@ spack: - mochi-thallium - mochi-bedrock-module-api - mochi-abt-io - - mochi-ssg+mpi - mochi-mona - mochi-flock - nlohmann-json @@ -20,7 +19,6 @@ spack: - py-attrs - py-typer - py-rich - - py-mochi-ssg - py-configspace concretizer: unify: true diff --git a/tests/spack.yaml b/tests/spack.yaml index 982dc7e..6396c6d 100644 --- a/tests/spack.yaml +++ b/tests/spack.yaml @@ -12,7 +12,6 @@ spack: - mochi-thallium - mochi-bedrock-module-api - mochi-abt-io - - mochi-ssg+mpi - mochi-mona - mochi-flock - nlohmann-json @@ -28,7 +27,6 @@ spack: - py-coverage - py-typer - py-rich - - py-mochi-ssg - py-configspace concretizer: unify: true From 9f2d1547bc12abd42f4b4a23b98ace92ea082327 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Wed, 4 Sep 2024 10:51:59 +0100 Subject: [PATCH 03/10] removed Mona --- CMakeLists.txt | 8 - include/bedrock/DependencyFinder.hpp | 1 - include/bedrock/Jx9Manager.hpp | 2 - include/bedrock/MargoManager.hpp | 4 - include/bedrock/MonaManager.hpp | 149 ----------------- python/mochi/bedrock/bedrockctl/__main__.py | 3 - python/mochi/bedrock/bedrockctl/mona.py | 96 ----------- python/mochi/bedrock/spec.py | 93 ----------- python/mochi/bedrock/test_dependencies.py | 44 ----- python/mochi/bedrock/test_server.py | 2 +- spack.yaml | 1 - src/CMakeLists.txt | 2 - src/DependencyFinder.cpp | 16 -- src/DependencyFinderImpl.hpp | 2 - src/MonaManager.cpp | 169 -------------------- src/MonaManagerImpl.hpp | 100 ------------ src/Server.cpp | 10 +- src/ServerImpl.hpp | 3 - src/bedrock-config.cmake.in | 3 - tests/InitJx9.cpp | 4 - tests/InitValid.cpp | 4 - tests/InvalidConfigs.json | 47 ------ tests/ValidConfigs.json | 20 +-- tests/spack.yaml | 1 - 24 files changed, 9 insertions(+), 775 deletions(-) delete mode 100644 include/bedrock/MonaManager.hpp delete mode 100644 python/mochi/bedrock/bedrockctl/mona.py delete mode 100644 src/MonaManager.cpp delete mode 100644 src/MonaManagerImpl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b1a2403..d8249f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,6 @@ option (ENABLE_COVERAGE "Enable code coverage" OFF) option (ENABLE_TESTS "Build tests" OFF) option (ENABLE_EXAMPLES "Build examples" OFF) option (ENABLE_MPI "Enable MPI support" OFF) -option (ENABLE_MONA "Enable MoNA support" OFF) option (ENABLE_FLOCK "Enable Flock support" OFF) option (ENABLE_ABT_IO "Enable ABT-IO support" OFF) option (ENABLE_PYTHON "Enable Python support" OFF) @@ -93,13 +92,6 @@ if (${ENABLE_MPI}) add_definitions (-DENABLE_MPI) set (OPTIONAL_MPI MPI::MPI_C) endif () -# search for mona -if (ENABLE_MONA) - pkg_check_modules (MONA REQUIRED IMPORTED_TARGET mona) - add_definitions (-DENABLE_MONA) - set (OPTIONAL_MONA PkgConfig::MONA) - set (OPTIONAL_SERVER_DEPS "${OPTIONAL_SERVER_DEPS} mona") -endif () # search for Python if (ENABLE_PYTHON) set (Python3_FIND_STRATEGY LOCATION) diff --git a/include/bedrock/DependencyFinder.hpp b/include/bedrock/DependencyFinder.hpp index 5c448f3..7e19445 100644 --- a/include/bedrock/DependencyFinder.hpp +++ b/include/bedrock/DependencyFinder.hpp @@ -45,7 +45,6 @@ class DependencyFinder { DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, const ABTioManager& abtio, - const MonaManager& mona, const ProviderManager& pmanager, const ClientManager& cmanager); diff --git a/include/bedrock/Jx9Manager.hpp b/include/bedrock/Jx9Manager.hpp index b207db5..8f1aba9 100644 --- a/include/bedrock/Jx9Manager.hpp +++ b/include/bedrock/Jx9Manager.hpp @@ -20,7 +20,6 @@ class Jx9ManagerImpl; class ABTioManager; class SSGManager; class SSGManagerImpl; -class MonaManager; class ClientManager; class ProviderManager; @@ -34,7 +33,6 @@ class Jx9Manager { friend class ABTioManager; friend class SSGManager; friend class SSGManagerImpl; - friend class MonaManager; friend class ClientManager; friend class ProviderManager; diff --git a/include/bedrock/MargoManager.hpp b/include/bedrock/MargoManager.hpp index 695b02a..4dafcfe 100644 --- a/include/bedrock/MargoManager.hpp +++ b/include/bedrock/MargoManager.hpp @@ -23,8 +23,6 @@ class SSGManager; class SSGData; class ABTioManager; class ABTioEntry; -class MonaManager; -class MonaEntry; class ProviderEntry; class ServerImpl; @@ -39,8 +37,6 @@ class MargoManager { friend class DependencyFinder; friend class SSGManager; friend class SSGEntry; - friend class MonaEntry; - friend class MonaManager; friend class ABTioEntry; friend class ABTioManager; friend class ProviderEntry; diff --git a/include/bedrock/MonaManager.hpp b/include/bedrock/MonaManager.hpp deleted file mode 100644 index 86007fd..0000000 --- a/include/bedrock/MonaManager.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * (C) 2022 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_MONA_MANAGER_HPP -#define __BEDROCK_MONA_MANAGER_HPP - -#include -#include -#include -#include - -/* Forward declaration to avoid including */ -typedef struct mona_instance* mona_instance_t; - -namespace bedrock { - -namespace tl = thallium; - -class Server; -class ServerImpl; -class DependencyFinder; -class MargoManager; -class MonaManagerImpl; -class Jx9Manager; - -/** - * @brief The MonaManager class encapsulates multiple MoNA instances. - */ -class MonaManager { - - friend class Server; - friend class ServerImpl; - friend class DependencyFinder; - - using json = nlohmann::json; - - public: - /** - * @brief Constructor from a configuration string. The configuration - * should be a JSON array listing MoNA instances in the following - * format: - * [ ... { "name" : "some_name", "pool" : "some_pool", "address" : "some_address" }, ... ] - * - * @param margoMgr MargoManager - * @param jx9 JX9 manager - * @param config JSON configuration of the manager. - * @param defaultProtocol default protocol to use if not specified in the JSON. - */ - MonaManager(const MargoManager& margo, - const Jx9Manager& jx9, - const json& config, - const std::string& defaultProtocol); - - /** - * @brief Copy-constructor. - */ - MonaManager(const MonaManager&); - - /** - * @brief Move-constructor. - */ - MonaManager(MonaManager&&); - - /** - * @brief Copy-assignment operator. - */ - MonaManager& operator=(const MonaManager&); - - /** - * @brief Move-assignment operator. - */ - MonaManager& operator=(MonaManager&&); - - /** - * @brief Destructor. - */ - ~MonaManager(); - - /** - * @brief Checks whether the MonaManager instance is valid. - */ - operator bool() const; - - /** - * @brief Get an internal Mona instance by its name. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the Mona instance. - */ - std::shared_ptr - getMonaInstance(const std::string& name) const; - - /** - * @brief Get the internal mona_instance_t by its index. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the Mona instance. - */ - std::shared_ptr - getMonaInstance(size_t index) const; - - /** - * @brief Returns the number of mona instances stored. - */ - size_t numMonaInstances() const; - - /** - * @brief Adds a Mona instance. - * - * @param name Name of the instance. - * @param pool Name of the pool to use. - * @param address Address to use.. - */ - std::shared_ptr - addMonaInstance(const std::string& name, - std::shared_ptr pool, - const std::string& address); - - /** - * @brief Adds a Mona instance from a JSON description. - * - * @param description JSON description. - * - * @return a NamedDependency representing the newly-created Mona instance. - */ - std::shared_ptr - addMonaInstanceFromJSON(const json& description); - - /** - * @brief Return the current JSON configuration. - */ - json getCurrentConfig() const; - - private: - std::shared_ptr self; - - inline operator std::shared_ptr() const { return self; } - - inline MonaManager(std::shared_ptr impl) - : self(std::move(impl)) {} -}; - -} // namespace bedrock - -#endif diff --git a/python/mochi/bedrock/bedrockctl/__main__.py b/python/mochi/bedrock/bedrockctl/__main__.py index d130ae3..5a99cca 100644 --- a/python/mochi/bedrock/bedrockctl/__main__.py +++ b/python/mochi/bedrock/bedrockctl/__main__.py @@ -24,9 +24,6 @@ from .abt_io import app as abt_io_app app.add_typer(abt_io_app, name="abtio", help="Access and modify ABT-IO instances") -from .mona import app as mona_app -app.add_typer(mona_app, name="mona", help="Access and modify MoNA instances") - @app.command() def status(): diff --git a/python/mochi/bedrock/bedrockctl/mona.py b/python/mochi/bedrock/bedrockctl/mona.py deleted file mode 100644 index 9585c0b..0000000 --- a/python/mochi/bedrock/bedrockctl/mona.py +++ /dev/null @@ -1,96 +0,0 @@ -import typer -from typing_extensions import Annotated -from enum import Enum -from typing import Optional, List -from ..spec import PoolSpec -from ..client import ClientException - - -app = typer.Typer() - - -@app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True}) -def create( - ctx: typer.Context, - name: Annotated[ - str, typer.Argument(help="Name of the MoNA instance to create")], - pool: Annotated[ - str, typer.Option( - "-p", "--pool", help="Pool for the MoNA instance to use")] = "__primary__", - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Create a new MoNA instance in the target Bedrock process(es). - """ - print("This command is not implemented yet") - raise typer.Exit(code=-1) - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import parse_config_from_args - config = parse_config_from_args(ctx.args) - mona = { - "name": name, - "pool": pool, - "config": config - } - from ._util import ServiceContext - with ServiceContext(target) as service: - for i in range(len(service)): - if not rank_is_in(i, ranks): - continue - try: - service[i].add_mona_instance(mona) - except ClientException as e: - print(f"Error adding MoNA instance in {service[i].address}: {str(e)}") - del service - - -@app.command() -def list(target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Lists the MoNA instances in each of the target Bedrock process(es). - """ - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import ServiceContext - from rich import print - with ServiceContext(target) as service: - config = { a: c["mona"] for a, c in service.config.items() } - for i in range(len(service)): - if not rank_is_in(i, ranks): - del config[service[i].address] - print(config) - del service - - -@app.command() -def remove( - name: Annotated[ - str, typer.Argument(help="Name of the MoNA instance to remove")], - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Remove an MoNA instance from the target Bedrock process(es). - """ - print("This command is not implemented yet") - raise typer.Exit(code=-1) - - -if __name__ == "__main__": - app() diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index 8536d09..b120954 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -1447,75 +1447,6 @@ def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'AbtIOSpec': return AbtIOSpec.from_dict(json.loads(json_string), abt_spec) -@attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) -class MonaSpec: - """MoNA instance specification. - - :param name: Name of the MoNA instance - :type name: str - - :param pool: Pool associated with the instance - :type pool: PoolSpec - - :param config: Configuration - :type config: dict - """ - - name: str = attr.ib( - validator=[instance_of(str), _validate_object_name], - on_setattr=attr.setters.frozen) - pool: PoolSpec = attr.ib(validator=instance_of(PoolSpec)) - config: dict = attr.ib(validator=instance_of(dict), - factory=dict) - - def to_dict(self) -> dict: - """Convert the MonaSpec into a dictionary. - """ - return {'name': self.name, - 'pool': self.pool.name, - 'config': self.config} - - @staticmethod - def from_dict(data: dict, abt_spec: ArgobotsSpec) -> 'MonaSpec': - """Construct a MonaSpec from a dictionary. Since the dictionary - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param data: Dictionary - :type data: dict - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - name = data['name'] - if 'config' in data: - config = data['config'] - else: - config = {} - pool = abt_spec.pools[data['pool']] - mona = MonaSpec(name=name, pool=pool, config=config) - return mona - - def to_json(self, *args, **kwargs) -> str: - """Convert the MonaSpec into a JSON string. - """ - return json.dumps(self.to_dict(), *args, **kwargs) - - @staticmethod - def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'MonaSpec': - """Construct an MonaSpec from a JSON string. Since the JSON string - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param json_string: JSON string - :type json_string: str - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - return MonaSpec.from_dict(json.loads(json_string), abt_spec) - - @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class ProviderSpec: """Provider specification. @@ -1831,9 +1762,6 @@ class ProcSpec: :param abt_io: List of AbtIOSpec :type abt_io: list - :param mona: List of MonaSpec - :type mona: list - :param libraries: Dictionary of libraries :type libraries: dict @@ -1850,9 +1778,6 @@ class ProcSpec: _abt_io: List[AbtIOSpec] = attr.ib( factory=list, validator=instance_of(list)) - _mona: List[MonaSpec] = attr.ib( - factory=list, - validator=instance_of(list)) libraries: dict = attr.ib( factory=dict, validator=instance_of(dict)) @@ -1874,13 +1799,6 @@ def abt_io(self) -> SpecListDecorator: """ return SpecListDecorator(list=self._abt_io, type=AbtIOSpec) - @property - def mona(self) -> SpecListDecorator: - """Return a decorator to access the internal list of MonaSpec - and validate changes to this list. - """ - return SpecListDecorator(list=self._mona, type=MonaSpec) - @property def providers(self) -> SpecListDecorator: """Return a decorator to access the internal list of ProviderSpec @@ -1900,7 +1818,6 @@ def to_dict(self) -> dict: """ data = {'margo': self.margo.to_dict(), 'abt_io': [a.to_dict() for a in self._abt_io], - 'mona': [m.to_dict() for m in self._mona], 'libraries': self.libraries, 'providers': [p.to_dict() for p in self._providers], 'clients': [c.to_dict() for c in self._clients], @@ -1913,7 +1830,6 @@ def from_dict(data: dict) -> 'ProcSpec': """ margo = MargoSpec.from_dict(data['margo']) abt_io = [] - mona = [] libraries = dict() providers = [] bedrock = {} @@ -1923,9 +1839,6 @@ def from_dict(data: dict) -> 'ProcSpec': if 'abt_io' in data: for a in data['abt_io']: abt_io.append(AbtIOSpec.from_dict(a, margo.argobots)) - if 'mona' in data: - for m in data['mona']: - mona.append(MonaSpec.from_dict(m, margo.argobots)) if 'providers' in data: for p in data['providers']: providers.append(ProviderSpec.from_dict(p, margo.argobots)) @@ -1936,7 +1849,6 @@ def from_dict(data: dict) -> 'ProcSpec': bedrock = BedrockSpec.from_dict(data['bedrock'], margo.argobots) return ProcSpec(margo=margo, abt_io=abt_io, - mona=mona, libraries=libraries, providers=providers, clients=clients, @@ -1962,11 +1874,6 @@ def validate(self) -> NoReturn: if p not in self.margo.argobots.pools: raise ValueError(f'Pool "{p.name}" used by ABT-IO instance' + ' not found in margo.argobots.pools') - for m in self._mona: - p = m.pool - if p not in self.margo.argobots.pools: - raise ValueError(f'Pool "{p.name}" used by MoNA instance' + - ' not found in margo.argobots.pools') for k, v in self.libraries.items(): if not isinstance(k, str): raise TypeError('Invalid key type found in libraries' + diff --git a/python/mochi/bedrock/test_dependencies.py b/python/mochi/bedrock/test_dependencies.py index 967e04c..bb66ab3 100644 --- a/python/mochi/bedrock/test_dependencies.py +++ b/python/mochi/bedrock/test_dependencies.py @@ -55,12 +55,6 @@ def setUp(self): "name": "my_abt_io", "pool": "__primary__" } - ], - "mona": [ - { - "name": "my_mona", - "pool": "__primary__" - } ] } self.server = mbs.Server(address="na+sm", config=config) @@ -286,44 +280,6 @@ def test_dependency_on_abt_io(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) - def test_dependency_on_mona(self): - providers = self.server.providers - self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "mona", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong dependency - client_params["dependencies"] = {"dep1": "my_mona_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_mona"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - - # Try creating a provider without the required dependency - provider_params = self.make_provider_params([ - {"name": "dep1", "type": "mona", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong dependency - provider_params["dependencies"] = {"dep1": "my_mona_bad"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the required dependency - provider_params["dependencies"] = {"dep1": "my_mona"} - providers.create(**provider_params) - self.assertEqual(len(providers), 3) - def test_dependency_on_client(self): providers = self.server.providers self.assertEqual(len(providers), 2) diff --git a/python/mochi/bedrock/test_server.py b/python/mochi/bedrock/test_server.py index 14ded06..bc62fed 100644 --- a/python/mochi/bedrock/test_server.py +++ b/python/mochi/bedrock/test_server.py @@ -36,7 +36,7 @@ def test_server_config(self): server = mbs.Server(address="na+sm") config = server.config self.assertIsInstance(config, dict) - for expected_key in ["margo", "abt_io", "bedrock", "providers", "clients", "libraries", "mona"]: + for expected_key in ["margo", "abt_io", "bedrock", "providers", "clients", "libraries"]: self.assertIn(expected_key, config) server.finalize() diff --git a/spack.yaml b/spack.yaml index 6a64708..20d745e 100644 --- a/spack.yaml +++ b/spack.yaml @@ -6,7 +6,6 @@ spack: - mochi-thallium - mochi-bedrock-module-api - mochi-abt-io - - mochi-mona - mochi-flock - nlohmann-json - nlohmann-json-schema-validator diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31249d4..c6aabc0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,6 @@ set (server-src-files Server.cpp ABTioManager.cpp MargoManager.cpp - MonaManager.cpp ProviderManager.cpp ClientManager.cpp DependencyFinder.cpp @@ -46,7 +45,6 @@ target_link_libraries (bedrock-server spdlog::spdlog fmt::fmt ${OPTIONAL_ABT_IO} - ${OPTIONAL_MONA} ${OPTIONAL_MPI}) target_include_directories (bedrock-server PUBLIC $) target_include_directories (bedrock-server BEFORE PUBLIC diff --git a/src/DependencyFinder.cpp b/src/DependencyFinder.cpp index c3e83df..d62d12f 100644 --- a/src/DependencyFinder.cpp +++ b/src/DependencyFinder.cpp @@ -19,14 +19,12 @@ namespace bedrock { DependencyFinder::DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, const ABTioManager& abtio, - const MonaManager& mona, const ProviderManager& pmanager, const ClientManager& cmanager) : self(std::make_shared(margo.getMargoInstance())) { self->m_mpi = mpi.self; self->m_margo_context = margo; self->m_abtio_context = abtio.self; - self->m_mona_context = mona.self; self->m_provider_manager = pmanager.self; self->m_client_manager = cmanager.self; } @@ -81,20 +79,6 @@ std::shared_ptr DependencyFinder::find( if (resolved) { *resolved = spec; } return abt_io; - } else if (type == "mona") { // MoNA instance - - auto mona_manager_impl = self->m_mona_context.lock(); - if (!mona_manager_impl) { - throw Exception("Could not resolve MoNA dependency: no MonaManager found"); - } - auto mona_id = MonaManager(mona_manager_impl).getMonaInstance(spec); - if (!mona_id) { - throw Exception("Could not find MoNA instance with name \"{}\"", - spec); - } - if (resolved) { *resolved = spec; } - return mona_id; - } else if (kind == BEDROCK_KIND_CLIENT) { auto client = findClient(type, spec); diff --git a/src/DependencyFinderImpl.hpp b/src/DependencyFinderImpl.hpp index 402f55a..6cfa7b4 100644 --- a/src/DependencyFinderImpl.hpp +++ b/src/DependencyFinderImpl.hpp @@ -8,7 +8,6 @@ #include "MargoManagerImpl.hpp" #include "ABTioManagerImpl.hpp" -#include "MonaManagerImpl.hpp" #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "Formatting.hpp" @@ -33,7 +32,6 @@ class DependencyFinderImpl { std::shared_ptr m_mpi; std::shared_ptr m_margo_context; std::weak_ptr m_abtio_context; - std::weak_ptr m_mona_context; std::weak_ptr m_provider_manager; std::weak_ptr m_client_manager; double m_timeout = 30.0; diff --git a/src/MonaManager.cpp b/src/MonaManager.cpp deleted file mode 100644 index c1a34c1..0000000 --- a/src/MonaManager.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * (C) 2022 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#include -#include -#include -#include "MonaManagerImpl.hpp" -#include "JsonUtil.hpp" -#include - -namespace tl = thallium; - -namespace bedrock { - -using nlohmann::json; - -MonaManager::MonaManager(const MargoManager& margoCtx, - const Jx9Manager& jx9, - const json& config, - const std::string& defaultAddress) -: self(std::make_shared()) { - self->m_default_address = defaultAddress; - self->m_margo_manager = margoCtx; - self->m_jx9_manager = jx9; - if (config.is_null()) return; -#ifndef ENABLE_MONA - (void)defaultAddress; - if (!(config.is_array() && config.empty())) - throw BEDROCK_DETAILED_EXCEPTION( - "Configuration has \"mona\" entry but Bedrock wasn't compiled with MoNA support"); -#else - if (!config.is_array()) { - throw BEDROCK_DETAILED_EXCEPTION("\"mona\" field should be an array"); - } - for(auto& description : config) { - addMonaInstanceFromJSON(description); - } -#endif -} - -// LCOV_EXCL_START - -MonaManager::MonaManager(const MonaManager&) = default; - -MonaManager::MonaManager(MonaManager&&) = default; - -MonaManager& MonaManager::operator=(const MonaManager&) = default; - -MonaManager& MonaManager::operator=(MonaManager&&) = default; - -MonaManager::~MonaManager() = default; - -MonaManager::operator bool() const { return static_cast(self); } - -// LCOV_EXCL_STOP - -std::shared_ptr -MonaManager::getMonaInstance(const std::string& name) const { -#ifndef ENABLE_MONA - (void)name; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiled with MoNA support"); -#else - auto guard = std::unique_lock{self->m_mtx}; - auto it = std::find_if(self->m_instances.begin(), self->m_instances.end(), - [&name](const auto& p) { return p->getName() == name; }); - if (it == self->m_instances.end()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find MoNA instance named \"{}\"", name); - return *it; -#endif -} - -std::shared_ptr MonaManager::getMonaInstance(size_t index) const { -#ifndef ENABLE_MONA - (void)index; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiled with MoNA support"); -#else - auto guard = std::unique_lock{self->m_mtx}; - if (index >= self->m_instances.size()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find MoNA instance at index {}", index); - return self->m_instances[index]; -#endif -} - - -size_t MonaManager::numMonaInstances() const { -#ifndef ENABLE_MONA - return 0; -#else - auto guard = std::unique_lock{self->m_mtx}; - return self->m_instances.size(); -#endif -} - -std::shared_ptr -MonaManager::addMonaInstance(const std::string& name, - std::shared_ptr pool, - const std::string& address) { -#ifndef ENABLE_MONA - (void)name; - (void)pool; - (void)address; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock wasn't compiled with MoNA support"); -#else - auto guard = std::unique_lock{self->m_mtx}; - // check if the name doesn't already exist - auto it = std::find_if( - self->m_instances.begin(), self->m_instances.end(), - [&name](const auto& instance) { return instance->getName() == name; }); - if (it != self->m_instances.end()) { - throw BEDROCK_DETAILED_EXCEPTION("Mona instance name \"{}\" already used", name); - } - // all good, can instanciate - mona_instance_t mona = mona_init_pool( - address.c_str(), true, nullptr, pool->getHandle()); - - if (!mona) { - throw BEDROCK_DETAILED_EXCEPTION("Could not initialize mona instance"); - } - auto entry = std::make_shared(name, mona, pool); - self->m_instances.push_back(entry); - return entry; -#endif -} - -std::shared_ptr -MonaManager::addMonaInstanceFromJSON(const json& description) { - static const json configSchema = R"( - { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "name": {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - "pool": {"oneOf": [ - {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - {"type": "integer", "minimum": 0 } - ]}, - "address": {"type": "string"} - }, - "required": ["name"] - } - )"_json; - static const JsonValidator validator{configSchema}; - validator.validate(description, "MonaManager"); - auto name = description["name"].get(); - auto address = description.value("address", self->m_default_address); - std::shared_ptr pool; - // find pool - if(description.contains("pool") && description["pool"].is_number()) { - pool = MargoManager(self->m_margo_manager) - .getPool(description["pool"].get()); - } else { - pool = MargoManager(self->m_margo_manager) - .getPool(description.value("pool", "__primary__")); - } - return addMonaInstance(name, pool, address); -} - -json MonaManager::getCurrentConfig() const { -#ifndef ENABLE_MONA - return json::array(); -#else - auto guard = std::unique_lock{self->m_mtx}; - return self->makeConfig(); -#endif -} - -} // namespace bedrock diff --git a/src/MonaManagerImpl.hpp b/src/MonaManagerImpl.hpp deleted file mode 100644 index c0d37b2..0000000 --- a/src/MonaManagerImpl.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * (C) 2022 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_MONA_CONTEXT_IMPL_H -#define __BEDROCK_MONA_CONTEXT_IMPL_H - -#include "bedrock/MargoManager.hpp" -#include "bedrock/MonaManager.hpp" -#include "bedrock/Jx9Manager.hpp" -#include "MargoManagerImpl.hpp" -#include -#include -#ifdef ENABLE_MONA -#include -#endif -#include -#include -#include - -namespace bedrock { - -using nlohmann::json; - -class MonaEntry : public NamedDependency { - - public: - -#ifdef ENABLE_MONA - std::shared_ptr pool; - - MonaEntry(const MonaEntry&) = delete; - MonaEntry(MonaEntry&&) = delete; - - template - MonaEntry(S&& name, mona_instance_t mona, std::shared_ptr p) - : NamedDependency(std::move(name), "mona", mona, releaseMonaInstance) - , pool(std::move(p)) {} - - static void releaseMonaInstance(void* args) { - auto mona_id = static_cast(args); - mona_finalize(mona_id); - } -#endif - - json makeConfig() const { - json config = json::object(); -#ifdef ENABLE_MONA - config["name"] = getName(); - config["pool"] = pool->getName(); - config["config"] = json::object(); - auto mona = getHandle(); - mona_addr_t self_addr; - na_return_t ret = mona_addr_self(mona, &self_addr); - if(ret != NA_SUCCESS) { - config["address"] = nullptr; - } else { - char self_addr_str[256]; - size_t self_addr_size = 256; - ret = mona_addr_to_string(mona, self_addr_str, &self_addr_size, self_addr); - if(ret != NA_SUCCESS) - config["address"] = nullptr; - else - config["address"] = std::string{self_addr_str}; - } -#endif - return config; - } - - ~MonaEntry() { - spdlog::trace("Finalizing MoNA instance {}", getName()); - } -}; - -class MonaManagerImpl { - - friend class MonaManager; - - public: - std::string m_default_address; - std::shared_ptr m_margo_manager; - std::shared_ptr m_jx9_manager; - std::vector> m_instances; - tl::mutex m_mtx; - - json makeConfig() const { - json config = json::array(); - for (auto& i : m_instances) { config.push_back(i->makeConfig()); } - return config; - } - - ~MonaManagerImpl() { - spdlog::trace("Finalizing MoNA"); - } -}; - -} // namespace bedrock - -#endif diff --git a/src/Server.cpp b/src/Server.cpp index 3103114..299ac5a 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -145,13 +144,6 @@ Server::Server(const std::string& address, const std::string& configString, self->m_abtio_manager = abtioMgr; spdlog::trace("ABTioManager initialized"); - // Initialize mona manager - spdlog::trace("Initializing MonaManager"); - auto& monaConfig = config["mona"]; - auto monaMgr = MonaManager(margoMgr, jx9Manager, monaConfig, address); - self->m_mona_manager = monaMgr; - spdlog::trace("MonaManager initialized"); - // Initializing the provider manager spdlog::trace("Initializing ProviderManager"); auto providerManager @@ -175,7 +167,7 @@ Server::Server(const std::string& address, const std::string& configString, // Initializing dependency finder spdlog::trace("Initializing DependencyFinder"); auto dependencyFinder = DependencyFinder( - mpi, margoMgr, abtioMgr, monaMgr, providerManager, clientManager); + mpi, margoMgr, abtioMgr, providerManager, clientManager); self->m_dependency_finder = dependencyFinder; self->m_dependency_finder->m_timeout = dependency_timeout; spdlog::trace("DependencyFinder initialized"); diff --git a/src/ServerImpl.hpp b/src/ServerImpl.hpp index 36f3752..0d82c4b 100644 --- a/src/ServerImpl.hpp +++ b/src/ServerImpl.hpp @@ -8,7 +8,6 @@ #include "MargoManagerImpl.hpp" #include "ABTioManagerImpl.hpp" -#include "MonaManagerImpl.hpp" #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "DependencyFinderImpl.hpp" @@ -34,7 +33,6 @@ class ServerImpl : public tl::provider { std::shared_ptr m_jx9_manager; std::shared_ptr m_margo_manager; std::shared_ptr m_abtio_manager; - std::shared_ptr m_mona_manager; std::shared_ptr m_client_manager; std::shared_ptr m_provider_manager; std::shared_ptr m_dependency_finder; @@ -88,7 +86,6 @@ class ServerImpl : public tl::provider { config["abt_io"] = m_abtio_manager->makeConfig(); config["clients"] = m_client_manager->makeConfig(); config["providers"] = m_provider_manager->makeConfig(); - config["mona"] = m_mona_manager->makeConfig(); config["libraries"] = json::parse(ModuleContext::getCurrentConfig()); config["bedrock"] = json::object(); config["bedrock"]["pool"] = m_pool->getName(); diff --git a/src/bedrock-config.cmake.in b/src/bedrock-config.cmake.in index 9c1791f..fbfed32 100644 --- a/src/bedrock-config.cmake.in +++ b/src/bedrock-config.cmake.in @@ -22,9 +22,6 @@ endif() if(@ENABLE_ABT_IO@) pkg_check_modules (ABTIO REQUIRED IMPORTED_TARGET abt-io) endif() -if(@ENABLE_MONA@) - pkg_check_modules (MONA REQUIRED IMPORTED_TARGET mona) -endif() check_required_components(bedrock) diff --git a/tests/InitJx9.cpp b/tests/InitJx9.cpp index 5691355..6a5ef20 100644 --- a/tests/InitJx9.cpp +++ b/tests/InitJx9.cpp @@ -12,10 +12,6 @@ static void cleanupOutputConfig(json& config) { for(auto& instance : config["abt_io"]) { instance["config"].erase("version"); } - for(auto& instance : config["mona"]) { - if(instance.contains("address")) - instance["address"] = ""; - } } static std::string jsonToJx9(const json& config) { diff --git a/tests/InitValid.cpp b/tests/InitValid.cpp index 94b6a4d..e77cfdd 100644 --- a/tests/InitValid.cpp +++ b/tests/InitValid.cpp @@ -14,10 +14,6 @@ static void cleanupOutputConfig(json& config) { for(auto& instance : config["abt_io"]) { instance["config"].erase("version"); } - for(auto& instance : config["mona"]) { - if(instance.contains("address")) - instance["address"] = ""; - } } TEST_CASE("Tests Server initialization", "[init-json]") { diff --git a/tests/InvalidConfigs.json b/tests/InvalidConfigs.json index 2ff429a..edc174c 100644 --- a/tests/InvalidConfigs.json +++ b/tests/InvalidConfigs.json @@ -39,53 +39,6 @@ "input": {"abt_io":[{"name":"my_abt_io","pool":"__primary__"},{"name":"my_abt_io","pool":"__primary__"}]} }, - - { - "test": "invalid mona section type", - "input": {"mona":123} - }, - - { - "test": "invalid mona instance type", - "input": {"mona":[123]} - }, - - { - "test": "invalid type for mona instance name", - "input": {"mona":[{"name":123}]} - }, - - { - "test": "invalid MoNA instance pool field type", - "input": {"mona":[{"pool":true}]} - }, - - { - "test": "two MoNA instances with the same name", - "input": {"mona":[{"name":"my_mona","pool":"__primary__"},{"name":"my_mona","pool":"__primary__"}]} - }, - - { - "test": "invalid MoNA instance pool name", - "input": {"mona":[{"pool":"abc"}]} - }, - - { - "test": "invalid MoNA instance pool index", - "input": {"mona":[{"pool":42}]} - }, - - { - "test": "invalid MoNA instance address type", - "input": {"mona":[{"pool":"__primary__","address":123}]} - }, - - { - "test": "invalid MoNA address", - "input": {"mona":[{"name":"my_mona","pool":"__primary__","address":"abc"}]} - }, - - { "test": "invalid type for libraries field", "input": {"libraries":123} diff --git a/tests/ValidConfigs.json b/tests/ValidConfigs.json index 75b588e..ae3e843 100644 --- a/tests/ValidConfigs.json +++ b/tests/ValidConfigs.json @@ -2,48 +2,42 @@ { "test": "empty configuration", "input": {}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"mona":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "using use_progress_thread and rpc_thread_count in Margo", "input": {"margo":{"use_progress_thread":true,"rpc_thread_count":2}}, - "output": {"abt_io":[],"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[],"mona":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[]} }, { "test": "defining an ABT-IO instance", "input": {"abt_io":[{"name":"my_abt_io","pool":"__primary__"}]}, - "output": {"abt_io":[{"config":{"internal_pool_flag":false,"liburing_flags":[],"null_io_read":false,"null_io_write":false,"num_urings":0,"trace_io":false},"name":"my_abt_io","pool":"__primary__"}],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[],"mona":[]} - }, - - { - "test": "defining a Mona instance", - "input": {"mona":[{"name":"my_mona", "pool":"__primary__"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[{"address":"","config":{},"name":"my_mona","pool":"__primary__"}],"providers":[]} + "output": {"abt_io":[{"config":{"internal_pool_flag":false,"liburing_flags":[],"null_io_read":false,"null_io_write":false,"num_urings":0,"trace_io":false},"name":"my_abt_io","pool":"__primary__"}],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "load a module library", "input": {"libraries":{"module_a":"./libModuleA.so"}}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "instantiate a provider from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a provider from module-a with simplified syntax", "input": {"libraries.module_a":"./libModuleA.so","providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a client from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"clients":[{"name":"my_client","type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"mona":[],"providers":[]} + "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} } ] diff --git a/tests/spack.yaml b/tests/spack.yaml index 6396c6d..3d9bb6a 100644 --- a/tests/spack.yaml +++ b/tests/spack.yaml @@ -12,7 +12,6 @@ spack: - mochi-thallium - mochi-bedrock-module-api - mochi-abt-io - - mochi-mona - mochi-flock - nlohmann-json - nlohmann-json-schema-validator From aacb892860812a4bcf5042c6628510bd42a1a6f2 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Wed, 4 Sep 2024 11:22:07 +0100 Subject: [PATCH 04/10] removed ABT-IO --- CMakeLists.txt | 9 - include/bedrock/ABTioManager.hpp | 160 ------------------ include/bedrock/DependencyFinder.hpp | 3 - include/bedrock/Jx9Manager.hpp | 6 - include/bedrock/MargoManager.hpp | 8 - include/bedrock/Server.hpp | 6 - include/bedrock/ServiceHandle.hpp | 9 - python/mochi/bedrock/bedrockctl/__main__.py | 3 - python/mochi/bedrock/bedrockctl/abt_io.py | 94 ----------- python/mochi/bedrock/client.py | 6 +- python/mochi/bedrock/server.py | 44 +---- python/mochi/bedrock/spec.py | 91 ----------- python/mochi/bedrock/test_abtio_manager.py | 71 -------- python/mochi/bedrock/test_dependencies.py | 44 ----- python/mochi/bedrock/test_server.py | 2 +- python/mochi/bedrock/test_service_handle.py | 32 +--- python/src/py-bedrock-client.cpp | 5 - python/src/py-bedrock-server.cpp | 18 -- spack.yaml | 1 - src/ABTioManager.cpp | 172 -------------------- src/ABTioManagerImpl.hpp | 91 ----------- src/CMakeLists.txt | 2 - src/DependencyFinder.cpp | 12 -- src/DependencyFinderImpl.hpp | 2 - src/Server.cpp | 13 +- src/ServerImpl.hpp | 19 --- src/ServiceHandle.cpp | 8 - src/bedrock-config.cmake.in | 7 +- tests/Client.cpp | 33 ---- tests/InitJx9.cpp | 3 - tests/InitValid.cpp | 3 - tests/InvalidConfigs.json | 40 ----- tests/ValidConfigs.json | 18 +- tests/spack.yaml | 1 - 34 files changed, 14 insertions(+), 1022 deletions(-) delete mode 100644 include/bedrock/ABTioManager.hpp delete mode 100644 python/mochi/bedrock/bedrockctl/abt_io.py delete mode 100644 python/mochi/bedrock/test_abtio_manager.py delete mode 100644 src/ABTioManager.cpp delete mode 100644 src/ABTioManagerImpl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8249f3..de7907e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,6 @@ option (ENABLE_TESTS "Build tests" OFF) option (ENABLE_EXAMPLES "Build examples" OFF) option (ENABLE_MPI "Enable MPI support" OFF) option (ENABLE_FLOCK "Enable Flock support" OFF) -option (ENABLE_ABT_IO "Enable ABT-IO support" OFF) option (ENABLE_PYTHON "Enable Python support" OFF) # library version set here (e.g. for shared libs). @@ -57,8 +56,6 @@ endif () # search for bedrock-module-api find_package (bedrock-module-api REQUIRED) -# search for pkg-config -find_package (PkgConfig REQUIRED) # search fo thallium find_package (thallium REQUIRED) # search for nlohmann/json and schema validator @@ -73,12 +70,6 @@ find_package (fmt REQUIRED) # search for toml11 find_package (toml11 REQUIRED) # search for abt-io -if (ENABLE_ABT_IO) - pkg_check_modules (ABTIO REQUIRED IMPORTED_TARGET abt-io) - add_definitions (-DENABLE_ABT_IO) - set (OPTIONAL_ABT_IO PkgConfig::ABTIO) - set (OPTIONAL_SERVER_DEPS "${OPTIONAL_SERVER_DEPS} abt-io") -endif () if (ENABLE_FLOCK) find_package (flock REQUIRED) add_definitions (-DENABLE_FLOCK) diff --git a/include/bedrock/ABTioManager.hpp b/include/bedrock/ABTioManager.hpp deleted file mode 100644 index ae2df38..0000000 --- a/include/bedrock/ABTioManager.hpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_ABTIO_MANAGER_HPP -#define __BEDROCK_ABTIO_MANAGER_HPP - -#include -#include -#include -#include - -/* Forward declaration to avoid including */ -typedef struct abt_io_instance* abt_io_instance_id; - -namespace bedrock { - -namespace tl = thallium; - -class Server; -class ServerImpl; -class MargoManager; -class DependencyFinder; -class ABTioManagerImpl; -class Jx9Manager; - -/** - * @brief The ABTioManager class is encapsulates multiple ABT-IO instances. - */ -class ABTioManager { - - friend class Server; - friend class ServerImpl; - friend class DependencyFinder; - - using json = nlohmann::json; - - public: - /** - * @brief Constructor from a configuration string. The configuration - * should be a JSON array listing ABT-IO instances in the following - * format: - * [ ... { "name" : "some_name", "pool" : "some_pool" }, ... ] - * - * @param margo_ctx Margo context. - * @param configString JSON configuration string. - */ - ABTioManager(const MargoManager& margo_ctx, - const Jx9Manager& jx9, - const json& config); - - /** - * @brief Copy-constructor. - */ - ABTioManager(const ABTioManager&); - - /** - * @brief Move-constructor. - */ - ABTioManager(ABTioManager&&); - - /** - * @brief Copy-assignment operator. - */ - ABTioManager& operator=(const ABTioManager&); - - /** - * @brief Move-assignment operator. - */ - ABTioManager& operator=(ABTioManager&&); - - /** - * @brief Destructor. - */ - ~ABTioManager(); - - /** - * @brief Checks whether the ABTioManager instance is valid. - */ - operator bool() const; - - /** - * @brief Get an internal abt-io instance by its name. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the ABT-IO instance. - */ - std::shared_ptr - getABTioInstance(const std::string& name) const; - - /** - * @brief Get an internal abt-io instance by its index. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the ABT-IO instance. - */ - std::shared_ptr - getABTioInstance(size_t index) const; - - /** - * @brief Returns the number of abt-io instances stored. - */ - size_t numABTioInstances() const; - - /** - * @brief Adds an ABT-IO instance. - * - * @param name Name of the instance. - * @param pool Name of the pool to use. - * @param config JSON configuration. - * - * @return the NamedDependency handle for the newly-created instance. - */ - std::shared_ptr - addABTioInstance(const std::string& name, - const std::shared_ptr& pool = {}, - const json& config = {}); - - - /** - * @brief Adds an ABT-IO istance as described by the - * provided JSON object. - * - * @param description ABT-IO instance description. - * - * @return the NamedDependency handle for the newly-created instance. - * - * Example of JSON description: - * - * ```json - * { - * "name": "my_abt_io_instance", - * "pool": "my_pool", - * "config": {} - * } - * ``` - */ - std::shared_ptr - addABTioInstanceFromJSON(const json& description); - - /** - * @brief Return the current JSON configuration. - */ - json getCurrentConfig() const; - - private: - std::shared_ptr self; - - inline operator std::shared_ptr() const { return self; } - - inline ABTioManager(std::shared_ptr impl) - : self(std::move(impl)) {} -}; - -} // namespace bedrock - -#endif diff --git a/include/bedrock/DependencyFinder.hpp b/include/bedrock/DependencyFinder.hpp index 7e19445..b557a83 100644 --- a/include/bedrock/DependencyFinder.hpp +++ b/include/bedrock/DependencyFinder.hpp @@ -7,7 +7,6 @@ #define __BEDROCK_DEPENDENCY_RESOLVER_HPP #include -#include #include #include #include @@ -38,13 +37,11 @@ class DependencyFinder { * @brief Constructor. * @param mpi MPI context * @param margo Margo context - * @param abtio ABT-IO context * @param pmanager Provider manager * @param cmanager Client manager */ DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, - const ABTioManager& abtio, const ProviderManager& pmanager, const ClientManager& cmanager); diff --git a/include/bedrock/Jx9Manager.hpp b/include/bedrock/Jx9Manager.hpp index 8f1aba9..5f60059 100644 --- a/include/bedrock/Jx9Manager.hpp +++ b/include/bedrock/Jx9Manager.hpp @@ -17,9 +17,6 @@ namespace bedrock { class Server; class ServerImpl; class Jx9ManagerImpl; -class ABTioManager; -class SSGManager; -class SSGManagerImpl; class ClientManager; class ProviderManager; @@ -30,9 +27,6 @@ class Jx9Manager { friend class Server; friend class ServerImpl; - friend class ABTioManager; - friend class SSGManager; - friend class SSGManagerImpl; friend class ClientManager; friend class ProviderManager; diff --git a/include/bedrock/MargoManager.hpp b/include/bedrock/MargoManager.hpp index 4dafcfe..dee16e9 100644 --- a/include/bedrock/MargoManager.hpp +++ b/include/bedrock/MargoManager.hpp @@ -19,10 +19,6 @@ class ProviderManager; class ClientManager; class DependencyFinder; class MargoManagerImpl; -class SSGManager; -class SSGData; -class ABTioManager; -class ABTioEntry; class ProviderEntry; class ServerImpl; @@ -35,10 +31,6 @@ class MargoManager { friend class ProviderManager; friend class ClientManager; friend class DependencyFinder; - friend class SSGManager; - friend class SSGEntry; - friend class ABTioEntry; - friend class ABTioManager; friend class ProviderEntry; friend class ServerImpl; diff --git a/include/bedrock/Server.hpp b/include/bedrock/Server.hpp index 039bf43..01fa818 100644 --- a/include/bedrock/Server.hpp +++ b/include/bedrock/Server.hpp @@ -7,7 +7,6 @@ #define __BEDROCK_SERVER_HPP #include -#include #include #include #include @@ -84,11 +83,6 @@ class Server { */ MargoManager getMargoManager() const; - /** - * @brief Get the underlying ABTioManager. - */ - ABTioManager getABTioManager() const; - /** * @brief Get the underlying ProviderManager. */ diff --git a/include/bedrock/ServiceHandle.hpp b/include/bedrock/ServiceHandle.hpp index 078f8a0..6551fd7 100644 --- a/include/bedrock/ServiceHandle.hpp +++ b/include/bedrock/ServiceHandle.hpp @@ -171,15 +171,6 @@ class ServiceHandle { void addClient(const std::string& description, AsyncRequest* req = nullptr) const; - /** - * @brief Creates a new ABT-IO instance on the target service daemon. - * - * @param description JSON description. - * @param req Asynchronous request to wait on, if provided. - */ - void addABTioInstance(const std::string& description, - AsyncRequest* req = nullptr) const; - /** * @brief Adds an Argobots pool to the Margo instance of * the target service. diff --git a/python/mochi/bedrock/bedrockctl/__main__.py b/python/mochi/bedrock/bedrockctl/__main__.py index 5a99cca..0ec0880 100644 --- a/python/mochi/bedrock/bedrockctl/__main__.py +++ b/python/mochi/bedrock/bedrockctl/__main__.py @@ -21,9 +21,6 @@ from .client import app as client_app app.add_typer(client_app, name="client", help="Access and modify clients") -from .abt_io import app as abt_io_app -app.add_typer(abt_io_app, name="abtio", help="Access and modify ABT-IO instances") - @app.command() def status(): diff --git a/python/mochi/bedrock/bedrockctl/abt_io.py b/python/mochi/bedrock/bedrockctl/abt_io.py deleted file mode 100644 index 13f1e26..0000000 --- a/python/mochi/bedrock/bedrockctl/abt_io.py +++ /dev/null @@ -1,94 +0,0 @@ -import typer -from typing_extensions import Annotated -from enum import Enum -from typing import Optional, List -from ..spec import PoolSpec -from ..client import ClientException - - -app = typer.Typer() - - -@app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True}) -def create( - ctx: typer.Context, - name: Annotated[ - str, typer.Argument(help="Name of the ABT-IO instance to create")], - pool: Annotated[ - str, typer.Option( - "-p", "--pool", help="Pool for the ABT-IO instance to use")] = "__primary__", - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Create a new ABT-IO instance in the target Bedrock process(es). - """ - from ._util import parse_config_from_args - config = parse_config_from_args(ctx.args) - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - abt_io = { - "name": name, - "pool": pool, - "config": config - } - from ._util import ServiceContext - with ServiceContext(target) as service: - for i in range(len(service)): - if not rank_is_in(i, ranks): - continue - try: - service[i].add_abtio_instance(abt_io) - except ClientException as e: - print(f"Error adding ABT-IO instance in {service[i].address}: {str(e)}") - del service - - -@app.command() -def list(target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Lists the ABT-IO instances in each of the target Bedrock process(es). - """ - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import ServiceContext - from rich import print - with ServiceContext(target) as service: - config = { a: c["abt_io"] for a, c in service.config.items() } - for i in range(len(service)): - if not rank_is_in(i, ranks): - del config[service[i].address] - print(config) - del service - - -@app.command() -def remove( - name: Annotated[ - str, typer.Argument(help="Name of the ABT-IO instance to remove")], - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Remove an ABT-IO instance from the target Bedrock process(es). - """ - print("This command is not implemented yet") - raise typer.Exit(code=-1) - - -if __name__ == "__main__": - app() diff --git a/python/mochi/bedrock/client.py b/python/mochi/bedrock/client.py index 0d35e0a..3e6890e 100644 --- a/python/mochi/bedrock/client.py +++ b/python/mochi/bedrock/client.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo import json -from .spec import ProcSpec, XstreamSpec, PoolSpec, AbtIOSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, XstreamSpec, PoolSpec, ProviderSpec, ClientSpec ClientException = pybedrock_client.Exception @@ -76,10 +76,6 @@ def add_xstream(self, config: str|dict|XstreamSpec): def remove_xstream(self, name: str): self._internal.remove_xstream(name) - def add_abtio_instance(self, description: str|dict|AbtIOSpec): - description = self._ensure_config_str(description) - self._internal.add_abtio_instance(description) - def add_client(self, description: str|dict|ClientSpec): description = self._ensure_config_str(description) self._internal.add_client(description) diff --git a/python/mochi/bedrock/server.py b/python/mochi/bedrock/server.py index cb4ff1a..a6e2948 100644 --- a/python/mochi/bedrock/server.py +++ b/python/mochi/bedrock/server.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo from typing import Mapping, List -from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, AbtIOSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, ProviderSpec, ClientSpec import json @@ -48,7 +48,6 @@ def handle(self): Pool = NamedDependency Xstream = NamedDependency -AbtIOInstance = NamedDependency Client = NamedDependency @@ -163,43 +162,6 @@ def default_handler_pool(self): return Pool(self._internal.default_handler_pool) -class AbtIOManager: - - def __init__(self, internal: pybedrock_server.ABTioManager, server: 'Server'): - self._internal = internal - self._server = server - - @property - def config(self): - return json.loads(self._internal.config) - - @property - def spec(self) -> list[AbtIOSpec]: - abt_spec = self._server.spec.margo.argobots - return [AbtIOSpec.from_dict(instance, abt_spec=abt_spec) for instance in self.config] - - def __len__(self) -> int: - return self._internal.num_abtio_instances - - def __getitem__(self, key: int|str) -> AbtIOInstance: - return AbtIOInstance(self._internal.get_abtio_instance(key)) - - def __contains__(self, key: str) -> bool: - try: - self.__getitem__(key) - return True - except BedrockException: - return False - - def create(self, name: str, pool: str|int|Pool, config: str|dict = {}) -> AbtIOInstance: - if isinstance(config, str): - config = json.loads(config) - if not isinstance(pool, Pool): - pool = self._server.margo.pools[pool] - pool = pool._internal - return AbtIOInstance(self._internal.add_abtio_instance(name, pool, config)) - - class ClientManager: def __init__(self, internal: pybedrock_server.ClientManager, server: 'Server'): @@ -362,10 +324,6 @@ def spec(self) -> ProcSpec: def margo(self) -> MargoManager: return MargoManager(self._internal.margo_manager, self) - @property - def abtio(self) -> AbtIOManager: - return AbtIOManager(self._internal.abtio_manager, self) - @property def clients(self) -> ClientManager: return ClientManager(self._internal.client_manager, self) diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index b120954..04c86f6 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -1381,72 +1381,6 @@ def from_config(*, config: 'Configuration', prefix: str = '', **kwargs): **extra) -@attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) -class AbtIOSpec: - """ABT-IO instance specification. - - :param name: Name of the ABT-IO instance - :type name: str - - :param pool: Pool associated with the instance - :type pool: PoolSpec - - :param config: Configuration - :type config: dict - """ - - name: str = attr.ib( - validator=[instance_of(str), _validate_object_name], - on_setattr=attr.setters.frozen) - pool: PoolSpec = attr.ib(validator=instance_of(PoolSpec)) - config: dict = attr.ib(validator=instance_of(dict), - factory=dict) - - def to_dict(self) -> dict: - """Convert the AbtIOSpec into a dictionary. - """ - return {'name': self.name, - 'pool': self.pool.name, - 'config': self.config} - - @staticmethod - def from_dict(data: dict, abt_spec: ArgobotsSpec) -> 'AbtIOSpec': - """Construct an AbtIOSpec from a dictionary. Since the dictionary - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param data: Dictionary - :type data: dict - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - name = data['name'] - config = data['config'] - pool = abt_spec.pools[data['pool']] - abtio = AbtIOSpec(name=name, pool=pool, config=config) - return abtio - - def to_json(self, *args, **kwargs) -> str: - """Convert the AbtIOSpec into a JSON string. - """ - return json.dumps(self.to_dict(), *args, **kwargs) - - @staticmethod - def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'AbtIOSpec': - """Construct an AbtIOSpec from a JSON string. Since the JSON string - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. - - :param json_string: JSON string - :type json_string: str - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec - """ - return AbtIOSpec.from_dict(json.loads(json_string), abt_spec) - - @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class ProviderSpec: """Provider specification. @@ -1759,9 +1693,6 @@ class ProcSpec: :param margo: Margo specification :type margo: MargoSpec - :param abt_io: List of AbtIOSpec - :type abt_io: list - :param libraries: Dictionary of libraries :type libraries: dict @@ -1775,9 +1706,6 @@ class ProcSpec: margo: MargoSpec = attr.ib( validator=instance_of(MargoSpec), converter=_margo_from_args) - _abt_io: List[AbtIOSpec] = attr.ib( - factory=list, - validator=instance_of(list)) libraries: dict = attr.ib( factory=dict, validator=instance_of(dict)) @@ -1792,13 +1720,6 @@ class ProcSpec: takes_self=True), validator=instance_of(BedrockSpec)) - @property - def abt_io(self) -> SpecListDecorator: - """Return a decorator to access the internal list of AbtIOSpec - and validate changes to this list. - """ - return SpecListDecorator(list=self._abt_io, type=AbtIOSpec) - @property def providers(self) -> SpecListDecorator: """Return a decorator to access the internal list of ProviderSpec @@ -1817,7 +1738,6 @@ def to_dict(self) -> dict: """Convert the ProcSpec into a dictionary. """ data = {'margo': self.margo.to_dict(), - 'abt_io': [a.to_dict() for a in self._abt_io], 'libraries': self.libraries, 'providers': [p.to_dict() for p in self._providers], 'clients': [c.to_dict() for c in self._clients], @@ -1829,16 +1749,12 @@ def from_dict(data: dict) -> 'ProcSpec': """Construct a ProcSpec from a dictionary. """ margo = MargoSpec.from_dict(data['margo']) - abt_io = [] libraries = dict() providers = [] bedrock = {} clients = [] if 'libraries' in data: libraries = data['libraries'] - if 'abt_io' in data: - for a in data['abt_io']: - abt_io.append(AbtIOSpec.from_dict(a, margo.argobots)) if 'providers' in data: for p in data['providers']: providers.append(ProviderSpec.from_dict(p, margo.argobots)) @@ -1848,7 +1764,6 @@ def from_dict(data: dict) -> 'ProcSpec': if 'bedrock' in data: bedrock = BedrockSpec.from_dict(data['bedrock'], margo.argobots) return ProcSpec(margo=margo, - abt_io=abt_io, libraries=libraries, providers=providers, clients=clients, @@ -1869,11 +1784,6 @@ def validate(self) -> NoReturn: """Validate the state of the ProcSpec. """ attr.validate(self) - for a in self._abt_io: - p = a.pool - if p not in self.margo.argobots.pools: - raise ValueError(f'Pool "{p.name}" used by ABT-IO instance' + - ' not found in margo.argobots.pools') for k, v in self.libraries.items(): if not isinstance(k, str): raise TypeError('Invalid key type found in libraries' + @@ -2131,7 +2041,6 @@ def from_config(config: 'Configuration', attr.resolve_types(MargoSpec, globals(), locals()) attr.resolve_types(ProviderSpec, globals(), locals()) attr.resolve_types(ClientSpec, globals(), locals()) -attr.resolve_types(AbtIOSpec, globals(), locals()) attr.resolve_types(BedrockSpec, globals(), locals()) attr.resolve_types(ProcSpec, globals(), locals()) attr.resolve_types(ServiceSpec, globals(), locals()) diff --git a/python/mochi/bedrock/test_abtio_manager.py b/python/mochi/bedrock/test_abtio_manager.py deleted file mode 100644 index f456d2b..0000000 --- a/python/mochi/bedrock/test_abtio_manager.py +++ /dev/null @@ -1,71 +0,0 @@ -import unittest -import pymargo.logging -import mochi.bedrock.server as mbs -import mochi.bedrock.spec as spec - - -class TestAbtIOManager(unittest.TestCase): - - def setUp(self): - config = { - "abt_io": [ - { - "name": "my_abtio", - "pool": "__primary__", - "config": {} - } - ] - } - self.server = mbs.Server(address="na+sm", config=config) - self.server.margo.engine.logger.set_log_level(pymargo.logging.level.critical) - - def tearDown(self): - self.server.finalize() - del self.server - - def test_get_abtio_manager(self): - abtio = self.server.abtio - self.assertIsInstance(abtio, mbs.AbtIOManager) - self.assertEqual(len(abtio), 1) - self.assertIn("my_abtio", abtio) - self.assertNotIn("not_my_abtio", abtio) - abtio_A = abtio[0] - abtio_B = abtio["my_abtio"] - self.assertEqual(abtio_A.name, abtio_B.name) - self.assertEqual(abtio_A.type, abtio_B.type) - self.assertEqual(abtio_A.handle, abtio_B.handle) - with self.assertRaises(mbs.BedrockException): - abtio[1] - with self.assertRaises(mbs.BedrockException): - abtio["bla"] - - def test_abtio_manager_config(self): - config = self.server.abtio.config - self.assertIsInstance(config, list) - self.assertEqual(len(config), 1) - abt_io_1 = config[0] - self.assertIsInstance(abt_io_1, dict) - for key in ["name", "pool", "config"]: - self.assertIn(key, abt_io_1) - - def test_abtio_manager_spec(self): - spec_list = self.server.abtio.spec - self.assertIsInstance(spec_list, list) - for s in spec_list: - self.assertIsInstance(s, spec.AbtIOSpec) - - def test_add_abtio_instance(self): - abtio = self.server.abtio - abtio.create( - name="my_abtio_2", - pool="__primary__") - self.assertEqual(len(abtio), 2) - abtio_A = abtio[1] - abtio_B = abtio["my_abtio_2"] - self.assertEqual(abtio_A.name, abtio_B.name) - self.assertEqual(abtio_A.type, abtio_B.type) - self.assertEqual(abtio_A.handle, abtio_B.handle) - - -if __name__ == '__main__': - unittest.main() diff --git a/python/mochi/bedrock/test_dependencies.py b/python/mochi/bedrock/test_dependencies.py index bb66ab3..64b0e34 100644 --- a/python/mochi/bedrock/test_dependencies.py +++ b/python/mochi/bedrock/test_dependencies.py @@ -49,12 +49,6 @@ def setUp(self): "name": "my_client_b", "type": "module_b" } - ], - "abt_io": [ - { - "name": "my_abt_io", - "pool": "__primary__" - } ] } self.server = mbs.Server(address="na+sm", config=config) @@ -242,44 +236,6 @@ def test_dependency_on_xstream(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) - def test_dependency_on_abt_io(self): - providers = self.server.providers - self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "abt_io", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client witht the wrong dependency - client_params["dependencies"] = {"dep1": "my_abt_io_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_abt_io"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - - # Try creating a provider without the required dependency - provider_params = self.make_provider_params([ - {"name": "dep1", "type": "abt_io", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong dependency - provider_params["dependencies"] = {"dep1": "my_abt_io_bad"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the required dependency - provider_params["dependencies"] = {"dep1": "my_abt_io"} - providers.create(**provider_params) - self.assertEqual(len(providers), 3) - def test_dependency_on_client(self): providers = self.server.providers self.assertEqual(len(providers), 2) diff --git a/python/mochi/bedrock/test_server.py b/python/mochi/bedrock/test_server.py index bc62fed..90d4f44 100644 --- a/python/mochi/bedrock/test_server.py +++ b/python/mochi/bedrock/test_server.py @@ -36,7 +36,7 @@ def test_server_config(self): server = mbs.Server(address="na+sm") config = server.config self.assertIsInstance(config, dict) - for expected_key in ["margo", "abt_io", "bedrock", "providers", "clients", "libraries"]: + for expected_key in ["margo", "bedrock", "providers", "clients", "libraries"]: self.assertIn(expected_key, config) server.finalize() diff --git a/python/mochi/bedrock/test_service_handle.py b/python/mochi/bedrock/test_service_handle.py index 6b2588c..227926a 100644 --- a/python/mochi/bedrock/test_service_handle.py +++ b/python/mochi/bedrock/test_service_handle.py @@ -52,7 +52,7 @@ def test_client(self): def test_config(self): config = self.sh.config self.assertIsInstance(config, dict) - for k in ["margo", "providers", "clients", "abt_io", "bedrock"]: + for k in ["margo", "providers", "clients", "bedrock"]: self.assertIn(k, config) def test_spec(self): @@ -180,36 +180,6 @@ def test_remove_xstream(self): with self.assertRaises(mbc.ClientException): self.server.margo.xstreams["my_xstream"] - def test_add_abtio_instance_from_dict(self): - abtio_config = { - "name": "my_abtio", - "pool": "__primary__", - "config": {} - } - self.sh.add_abtio_instance(abtio_config) - abtio = self.server.abtio["my_abtio"] - self.assertIsInstance(abtio, mbs.AbtIOInstance) - - def test_add_abtio_instance_from_src(self): - abtio_config = { - "name": "my_abtio", - "pool": "__primary__", - "config": {} - } - self.sh.add_abtio_instance(json.dumps(abtio_config)) - abtio = self.server.abtio["my_abtio"] - self.assertIsInstance(abtio, mbs.AbtIOInstance) - - def test_add_abtio_instance_from_spec(self): - abtio_config = spec.AbtIOSpec( - name="my_abtio", - pool=spec.PoolSpec(name="__primary__", kind="fifo_wait", access="mpmc"), - config={} - ) - self.sh.add_abtio_instance(abtio_config) - abtio = self.server.abtio["my_abtio"] - self.assertIsInstance(abtio, mbs.AbtIOInstance) - def test_add_client_from_dict(self): self.test_load_module() client_config = { diff --git a/python/src/py-bedrock-client.cpp b/python/src/py-bedrock-client.cpp index ffef4fe..1b0c583 100644 --- a/python/src/py-bedrock-client.cpp +++ b/python/src/py-bedrock-client.cpp @@ -97,11 +97,6 @@ PYBIND11_MODULE(pybedrock_client, m) { const std::string& description) { sh.addClient(description); }, "description"_a) - .def("add_abtio_instance", - [](const ServiceHandle& sh, - const std::string& description) { - sh.addABTioInstance(description); - }, "description"_a = std::string("{}")) .def("add_pool", [](const ServiceHandle& sh, const std::string& config) { sh.addPool(config); }, diff --git a/python/src/py-bedrock-server.cpp b/python/src/py-bedrock-server.cpp index 637e340..27525bd 100644 --- a/python/src/py-bedrock-server.cpp +++ b/python/src/py-bedrock-server.cpp @@ -78,10 +78,6 @@ PYBIND11_MODULE(pybedrock_server, m) { [](std::shared_ptr server) { return server->getMargoManager(); }) - .def_property_readonly("abtio_manager", - [](std::shared_ptr server) { - return server->getABTioManager(); - }) .def_property_readonly("provider_manager", [](std::shared_ptr server) { return server->getProviderManager(); @@ -130,20 +126,6 @@ PYBIND11_MODULE(pybedrock_server, m) { .def_property_readonly("num_xstreams", &MargoManager::getNumXstreams) ; - py11::class_ (m, "ABTioManager") - .def_property_readonly("config", [](const ABTioManager& manager) { - return manager.getCurrentConfig().dump(); - }) - .def_property_readonly("num_abtio_instances", &ABTioManager::numABTioInstances) - .def("get_abtio_instance", [](const ABTioManager& abtio, const std::string& name) { - return abtio.getABTioInstance(name); - }, "name"_a) - .def("get_abtio_instance", [](const ABTioManager& abtio, size_t index) { - return abtio.getABTioInstance(index); - }, "index"_a) - .def("add_abtio_instance", &ABTioManager::addABTioInstance) - ; - py11::class_ (m, "ProviderManager") .def_property_readonly("config", &ProviderManager::getCurrentConfig) .def_property_readonly("num_providers", &ProviderManager::numProviders) diff --git a/spack.yaml b/spack.yaml index 20d745e..d124f4d 100644 --- a/spack.yaml +++ b/spack.yaml @@ -5,7 +5,6 @@ spack: - mochi-margo - mochi-thallium - mochi-bedrock-module-api - - mochi-abt-io - mochi-flock - nlohmann-json - nlohmann-json-schema-validator diff --git a/src/ABTioManager.cpp b/src/ABTioManager.cpp deleted file mode 100644 index 4532301..0000000 --- a/src/ABTioManager.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#include -#include -#include -#include -#include "JsonUtil.hpp" -#include "ABTioManagerImpl.hpp" -#include - -namespace tl = thallium; - -namespace bedrock { - -using nlohmann::json; - -ABTioManager::ABTioManager(const MargoManager& margoCtx, - const Jx9Manager& jx9, - const json& config) -: self(std::make_shared()) { - self->m_margo_manager = margoCtx; - self->m_jx9_manager = jx9; - if (config.is_null()) return; -#ifndef ENABLE_ABT_IO - if (!(config.is_array() && config.empty())) - throw BEDROCK_DETAILED_EXCEPTION( - "Configuration has an \"abt_io\" field but Bedrock wasn't compiled with ABT-IO support"); -#else - if (!config.is_array()) { - throw BEDROCK_DETAILED_EXCEPTION("\"abt_io\" field in configuration should be an array"); - } - for(auto& description : config) { - addABTioInstanceFromJSON(description); - } -#endif -} - -// LCOV_EXCL_START - -ABTioManager::ABTioManager(const ABTioManager&) = default; - -ABTioManager::ABTioManager(ABTioManager&&) = default; - -ABTioManager& ABTioManager::operator=(const ABTioManager&) = default; - -ABTioManager& ABTioManager::operator=(ABTioManager&&) = default; - -ABTioManager::~ABTioManager() = default; - -ABTioManager::operator bool() const { return static_cast(self); } - -// LCOV_EXCL_STOP - -std::shared_ptr -ABTioManager::getABTioInstance(const std::string& name) const { -#ifndef ENABLE_ABT_IO - (void)name; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiler with ABT-IO support"); -#else - auto it = std::find_if(self->m_instances.begin(), self->m_instances.end(), - [&name](const auto& p) { return p->getName() == name; }); - if (it == self->m_instances.end()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find ABT-IO instance \"{}\"", name); - return *it; -#endif -} - -std::shared_ptr -ABTioManager::getABTioInstance(size_t index) const { -#ifndef ENABLE_ABT_IO - (void)index; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiler with ABT-IO support"); -#else - if (index >= self->m_instances.size()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find ABT-IO instance at index {}", index); - return self->m_instances[index]; -#endif -} - -size_t ABTioManager::numABTioInstances() const { -#ifndef ENABLE_ABT_IO - return 0; -#else - return self->m_instances.size(); -#endif -} - -std::shared_ptr -ABTioManager::addABTioInstance(const std::string& name, - const std::shared_ptr& pool, - const json& config) { -#ifndef ENABLE_ABT_IO - (void)name; - (void)pool; - (void)config; - throw BEDROCK_DETAILED_EXCEPTION("Bedrock was not compiled with ABT-IO support"); -#else - json abt_io_config; - // check if the name doesn't already exist - auto it = std::find_if( - self->m_instances.begin(), self->m_instances.end(), - [&name](const auto& instance) { return instance->getName() == name; }); - if (it != self->m_instances.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "ABT-IO instance name \"{}\" already used", - name); - } - // get the config of this ABT-IO instance - if (!config.is_object() && !config.is_null()) { - throw BEDROCK_DETAILED_EXCEPTION( - "\"config\" field in ABT-IO instance configuration should be an object"); - } - // all good, can instanciate - abt_io_init_info abt_io_info; - auto configStr = config.is_null() ? std::string{"{}"} : config.dump(); - abt_io_info.json_config = configStr.c_str(); - abt_io_info.progress_pool = pool->getHandle(); - abt_io_instance_id abt_io = abt_io_init_ext(&abt_io_info); - if (abt_io == ABT_IO_INSTANCE_NULL) { - throw BEDROCK_DETAILED_EXCEPTION("Could not initialize ABT-IO instance \"{}\"", name); - } - auto entry = std::make_shared(name, abt_io, pool); - self->m_instances.push_back(entry); - return entry; -#endif -} - -std::shared_ptr -ABTioManager::addABTioInstanceFromJSON(const json& description) { - static const json configSchema = R"( - { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "name": {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - "pool": {"oneOf": [ - {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - {"type": "integer", "minimum": 0 } - ]}, - "config": {"type": "object"} - }, - "required": ["name"] - } - )"_json; - static const JsonValidator validator{configSchema}; - validator.validate(description, "ABTioManager"); - auto name = description["name"].get(); - auto config = description.value("config", json::object()); - std::shared_ptr pool; - // find pool - if(description.contains("pool") && description["pool"].is_number()) { - pool = MargoManager(self->m_margo_manager) - .getPool(description["pool"].get()); - } else { - pool = MargoManager(self->m_margo_manager) - .getPool(description.value("pool", "__primary__")); - } - return addABTioInstance(name, pool, config); -} - -json ABTioManager::getCurrentConfig() const { -#ifndef ENABLE_ABT_IO - return json::array(); -#else - return self->makeConfig(); -#endif -} - -} // namespace bedrock diff --git a/src/ABTioManagerImpl.hpp b/src/ABTioManagerImpl.hpp deleted file mode 100644 index 23aee55..0000000 --- a/src/ABTioManagerImpl.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_ABTIO_CONTEXT_IMPL_H -#define __BEDROCK_ABTIO_CONTEXT_IMPL_H - -#include "bedrock/MargoManager.hpp" -#include "bedrock/ABTioManager.hpp" -#include "bedrock/NamedDependency.hpp" -#include "MargoManagerImpl.hpp" -#include "Jx9ManagerImpl.hpp" -#include -#include -#include -#include -#include - -#ifdef ENABLE_ABT_IO -#include -#else -inline char* abt_io_get_config(abt_io_instance_id) { return nullptr; } -inline void abt_io_finalize(abt_io_instance_id) {} -#endif - - -namespace bedrock { - -using nlohmann::json; - -class ABTioEntry : public NamedDependency { - - public: - - std::shared_ptr pool; - - json makeConfig() const { - json config = json::object(); - config["name"] = getName(); - config["pool"] = pool->getName(); - auto c = abt_io_get_config(getHandle()); - config["config"] = c ? json::parse(c) : json::object(); - free(c); - return config; - } - - template - ABTioEntry( - S&& name, - abt_io_instance_id abt_io_id, - std::shared_ptr p) - : NamedDependency( - std::forward(name), - "abt_io", - abt_io_id, - releaseABTioEntry) - , pool(std::move(p)) - {} - - ABTioEntry(const ABTioEntry&) = delete; - ABTioEntry(ABTioEntry&& other) = delete; - - static void releaseABTioEntry(void* args) { - auto abt_io_id = static_cast(args); - if(!abt_io_id) return; - abt_io_finalize(abt_io_id); - } - - ~ABTioEntry() { - spdlog::trace("Freeing ABT-IO instance {}", getName()); - } -}; - -class ABTioManagerImpl { - - public: - std::shared_ptr m_margo_manager; - std::shared_ptr m_jx9_manager; - std::vector> m_instances; - - json makeConfig() const { - json config = json::array(); - for (auto& i : m_instances) { config.push_back(i->makeConfig()); } - return config; - } -}; - -} // namespace bedrock - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6aabc0..4df42a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,6 @@ # set source files set (server-src-files Server.cpp - ABTioManager.cpp MargoManager.cpp ProviderManager.cpp ClientManager.cpp @@ -44,7 +43,6 @@ target_link_libraries (bedrock-server nlohmann_json::nlohmann_json spdlog::spdlog fmt::fmt - ${OPTIONAL_ABT_IO} ${OPTIONAL_MPI}) target_include_directories (bedrock-server PUBLIC $) target_include_directories (bedrock-server BEFORE PUBLIC diff --git a/src/DependencyFinder.cpp b/src/DependencyFinder.cpp index d62d12f..229eaba 100644 --- a/src/DependencyFinder.cpp +++ b/src/DependencyFinder.cpp @@ -18,13 +18,11 @@ namespace bedrock { DependencyFinder::DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, - const ABTioManager& abtio, const ProviderManager& pmanager, const ClientManager& cmanager) : self(std::make_shared(margo.getMargoInstance())) { self->m_mpi = mpi.self; self->m_margo_context = margo; - self->m_abtio_context = abtio.self; self->m_provider_manager = pmanager.self; self->m_client_manager = cmanager.self; } @@ -69,16 +67,6 @@ std::shared_ptr DependencyFinder::find( if (resolved) { *resolved = spec; } return xstream; - } else if (type == "abt_io") { // ABTIO instance - - auto abtio_manager_impl = self->m_abtio_context.lock(); - if (!abtio_manager_impl) { - throw Exception("Could not resolve ABT-IO dependency: no ABTioManager found"); - } - auto abt_io = ABTioManager(abtio_manager_impl).getABTioInstance(spec); - if (resolved) { *resolved = spec; } - return abt_io; - } else if (kind == BEDROCK_KIND_CLIENT) { auto client = findClient(type, spec); diff --git a/src/DependencyFinderImpl.hpp b/src/DependencyFinderImpl.hpp index 6cfa7b4..fc2a64a 100644 --- a/src/DependencyFinderImpl.hpp +++ b/src/DependencyFinderImpl.hpp @@ -7,7 +7,6 @@ #define __BEDROCK_DEPENDENCY_FINDER_IMPL_H #include "MargoManagerImpl.hpp" -#include "ABTioManagerImpl.hpp" #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "Formatting.hpp" @@ -31,7 +30,6 @@ class DependencyFinderImpl { tl::engine m_engine; std::shared_ptr m_mpi; std::shared_ptr m_margo_context; - std::weak_ptr m_abtio_context; std::weak_ptr m_provider_manager; std::weak_ptr m_client_manager; double m_timeout = 30.0; diff --git a/src/Server.cpp b/src/Server.cpp index 299ac5a..064fbe0 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -5,7 +5,6 @@ */ #include #include -#include #include #include #include @@ -137,13 +136,6 @@ Server::Server(const std::string& address, const std::string& configString, try { - // Initialize abt-io context - spdlog::trace("Initializing ABTioManager"); - auto& abtioConfig = config["abt_io"]; - auto abtioMgr = ABTioManager(margoMgr, jx9Manager, abtioConfig); - self->m_abtio_manager = abtioMgr; - spdlog::trace("ABTioManager initialized"); - // Initializing the provider manager spdlog::trace("Initializing ProviderManager"); auto providerManager @@ -166,8 +158,7 @@ Server::Server(const std::string& address, const std::string& configString, // Initializing dependency finder spdlog::trace("Initializing DependencyFinder"); - auto dependencyFinder = DependencyFinder( - mpi, margoMgr, abtioMgr, providerManager, clientManager); + auto dependencyFinder = DependencyFinder(mpi, margoMgr, providerManager, clientManager); self->m_dependency_finder = dependencyFinder; self->m_dependency_finder->m_timeout = dependency_timeout; spdlog::trace("DependencyFinder initialized"); @@ -198,8 +189,6 @@ Server::~Server() {} MargoManager Server::getMargoManager() const { return self->m_margo_manager; } -ABTioManager Server::getABTioManager() const { return self->m_abtio_manager; } - ProviderManager Server::getProviderManager() const { return self->m_provider_manager; } diff --git a/src/ServerImpl.hpp b/src/ServerImpl.hpp index 0d82c4b..512665f 100644 --- a/src/ServerImpl.hpp +++ b/src/ServerImpl.hpp @@ -7,7 +7,6 @@ #define __BEDROCK_SERVER_IMPL_H #include "MargoManagerImpl.hpp" -#include "ABTioManagerImpl.hpp" #include "ProviderManagerImpl.hpp" #include "ClientManagerImpl.hpp" #include "DependencyFinderImpl.hpp" @@ -32,7 +31,6 @@ class ServerImpl : public tl::provider { std::shared_ptr m_mpi; std::shared_ptr m_jx9_manager; std::shared_ptr m_margo_manager; - std::shared_ptr m_abtio_manager; std::shared_ptr m_client_manager; std::shared_ptr m_provider_manager; std::shared_ptr m_dependency_finder; @@ -41,7 +39,6 @@ class ServerImpl : public tl::provider { tl::remote_procedure m_get_config_rpc; tl::remote_procedure m_query_config_rpc; - tl::remote_procedure m_add_abtio_rpc; tl::remote_procedure m_add_pool_rpc; tl::remote_procedure m_add_xstream_rpc; @@ -58,8 +55,6 @@ class ServerImpl : public tl::provider { define("bedrock_get_config", &ServerImpl::getConfigRPC, m_tl_pool)), m_query_config_rpc( define("bedrock_query_config", &ServerImpl::queryConfigRPC, m_tl_pool)), - m_add_abtio_rpc( - define("bedrock_add_abtio", &ServerImpl::addABTioRPC, m_tl_pool)), m_add_pool_rpc( define("bedrock_add_pool", &ServerImpl::addPoolRPC, m_tl_pool)), m_add_xstream_rpc( @@ -73,7 +68,6 @@ class ServerImpl : public tl::provider { ~ServerImpl() { m_get_config_rpc.deregister(); m_query_config_rpc.deregister(); - m_add_abtio_rpc.deregister(); m_add_pool_rpc.deregister(); m_add_xstream_rpc.deregister(); m_remove_pool_rpc.deregister(); @@ -83,7 +77,6 @@ class ServerImpl : public tl::provider { json makeConfig() const { auto config = json::object(); config["margo"] = m_margo_manager->makeConfig(); - config["abt_io"] = m_abtio_manager->makeConfig(); config["clients"] = m_client_manager->makeConfig(); config["providers"] = m_provider_manager->makeConfig(); config["libraries"] = json::parse(ModuleContext::getCurrentConfig()); @@ -114,18 +107,6 @@ class ServerImpl : public tl::provider { req.respond(result); } - void addABTioRPC(const tl::request& req, const std::string& description) { - RequestResult result; - result.success() = true; - try { - ABTioManager(m_abtio_manager).addABTioInstanceFromJSON(json::parse(description)); - } catch (const std::exception& ex) { - result.error() = ex.what(); - result.success() = false; - } - req.respond(result); - } - void addPoolRPC(const tl::request& req, const std::string& config) { RequestResult result; result.success() = true; diff --git a/src/ServiceHandle.cpp b/src/ServiceHandle.cpp index 18eaecb..69420af 100644 --- a/src/ServiceHandle.cpp +++ b/src/ServiceHandle.cpp @@ -162,14 +162,6 @@ void ServiceHandle::addClient(const std::string& description, SEND_RPC_WITH_BOOL_RESULT(description); } -void ServiceHandle::addABTioInstance(const std::string& description, - AsyncRequest* req) const { - if (not self) throw BEDROCK_DETAILED_EXCEPTION("Invalid bedrock::ServiceHandle object"); - auto& rpc = self->m_client->m_add_abtio; - auto& ph = self->m_ph; - SEND_RPC_WITH_BOOL_RESULT(description); -} - void ServiceHandle::addPool(const std::string& config, AsyncRequest* req) const { if (not self) throw BEDROCK_DETAILED_EXCEPTION("Invalid bedrock::ServiceHandle object"); diff --git a/src/bedrock-config.cmake.in b/src/bedrock-config.cmake.in index fbfed32..98df1d0 100644 --- a/src/bedrock-config.cmake.in +++ b/src/bedrock-config.cmake.in @@ -12,15 +12,14 @@ include (CMakeFindDependencyMacro) find_dependency (nlohmann_json) find_dependency (thallium) find_dependency (spdlog) -find_dependency (PkgConfig) find_dependency (fmt) -pkg_check_modules (MARGO REQUIRED IMPORTED_TARGET margo) if(@ENABLE_MPI@) find_dependency (MPI) endif() -if(@ENABLE_ABT_IO@) - pkg_check_modules (ABTIO REQUIRED IMPORTED_TARGET abt-io) + +if(@ENABLE_FLOCK@) + find_dependency (flock) endif() check_required_components(bedrock) diff --git a/tests/Client.cpp b/tests/Client.cpp index 3b1f280..111ea50 100644 --- a/tests/Client.cpp +++ b/tests/Client.cpp @@ -106,39 +106,6 @@ TEST_CASE("Tests various object creation and removal via a ServiceHandle", "[ser REQUIRE_THROWS_AS(req.wait(), bedrock::Exception); } - SECTION("Add and remove ABT-IO instances remotely") { - // add ABT-IO instance synchronously - constexpr const char* my_abt_io1 = R"( - { "name": "my_abt_io1", "pool": "__primary__" } - )"; - serviceHandle.addABTioInstance(my_abt_io1); - auto output_config = json::parse(server.getCurrentConfig()); - auto abt_io = output_config["abt_io"]; - REQUIRE(std::find_if(abt_io.begin(), abt_io.end(), - [](auto& x) { return x["name"] == "my_abt_io1"; }) - != abt_io.end()); - // add ABT-IO instance asynchronously - bedrock::AsyncRequest req; - constexpr const char* my_abt_io2 = R"( - { "name": "my_abt_io2", "pool": "__primary__", "config": {} } - )"; - serviceHandle.addABTioInstance(my_abt_io2, &req); - req.wait(); - output_config = json::parse(server.getCurrentConfig()); - abt_io = output_config["abt_io"]; - REQUIRE(std::find_if(abt_io.begin(), abt_io.end(), - [](auto& x) { return x["name"] == "my_abt_io2"; }) - != abt_io.end()); - // add ABT-IO instance with invalid configuration - constexpr const char* my_abt_io3 = R"( - { "name": "my_abt_io2", "pool": "1234" } - )"; - REQUIRE_THROWS_AS( - serviceHandle.addABTioInstance(my_abt_io3), - bedrock::Exception); - // TODO: add removal when we have the functionality for it - } - SECTION("Load a library") { // load libModuleA.so synchronously serviceHandle.loadModule("module_a", "./libModuleA.so"); diff --git a/tests/InitJx9.cpp b/tests/InitJx9.cpp index 6a5ef20..677e298 100644 --- a/tests/InitJx9.cpp +++ b/tests/InitJx9.cpp @@ -9,9 +9,6 @@ using json = nlohmann::json; static void cleanupOutputConfig(json& config) { config["margo"].erase("mercury"); config["margo"].erase("version"); - for(auto& instance : config["abt_io"]) { - instance["config"].erase("version"); - } } static std::string jsonToJx9(const json& config) { diff --git a/tests/InitValid.cpp b/tests/InitValid.cpp index e77cfdd..8c33849 100644 --- a/tests/InitValid.cpp +++ b/tests/InitValid.cpp @@ -11,9 +11,6 @@ using json = nlohmann::json; static void cleanupOutputConfig(json& config) { config["margo"].erase("mercury"); config["margo"].erase("version"); - for(auto& instance : config["abt_io"]) { - instance["config"].erase("version"); - } } TEST_CASE("Tests Server initialization", "[init-json]") { diff --git a/tests/InvalidConfigs.json b/tests/InvalidConfigs.json index edc174c..976a025 100644 --- a/tests/InvalidConfigs.json +++ b/tests/InvalidConfigs.json @@ -1,44 +1,4 @@ [ - { - "test": "invalid ABT-IO section", - "input": {"abt_io":123} - }, - - { - "test": "invalid type of ABT-IO instance configuration", - "input": {"abt_io":[123]} - }, - - { - "test": "invalid ABT-IO instance name", - "input": {"abt_io":[{"name":123}]} - }, - - { - "test": "invalid ABT-IO instance pool name", - "input": {"abt_io":[{"pool":"abc"}]} - }, - - { - "test": "invalid ABT-IO instance pool index", - "input": {"abt_io":[{"pool":42}]} - }, - - { - "test": "invalid ABT-IO instance pool field type", - "input": {"abt_io":[{"pool":true}]} - }, - - { - "test": "invalid ABT-IO instance config field type", - "input": {"abt_io":[{"pool":"__primary__","config":true}]} - }, - - { - "test": "two ABT-IO instances with the same name", - "input": {"abt_io":[{"name":"my_abt_io","pool":"__primary__"},{"name":"my_abt_io","pool":"__primary__"}]} - }, - { "test": "invalid type for libraries field", "input": {"libraries":123} diff --git a/tests/ValidConfigs.json b/tests/ValidConfigs.json index ae3e843..861626a 100644 --- a/tests/ValidConfigs.json +++ b/tests/ValidConfigs.json @@ -2,42 +2,36 @@ { "test": "empty configuration", "input": {}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "using use_progress_thread and rpc_thread_count in Margo", "input": {"margo":{"use_progress_thread":true,"rpc_thread_count":2}}, - "output": {"abt_io":[],"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[]} - }, - - { - "test": "defining an ABT-IO instance", - "input": {"abt_io":[{"name":"my_abt_io","pool":"__primary__"}]}, - "output": {"abt_io":[{"config":{"internal_pool_flag":false,"liburing_flags":[],"null_io_read":false,"null_io_write":false,"num_urings":0,"trace_io":false},"name":"my_abt_io","pool":"__primary__"}],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "output": {"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[]} }, { "test": "load a module library", "input": {"libraries":{"module_a":"./libModuleA.so"}}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "instantiate a provider from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a provider from module-a with simplified syntax", "input": {"libraries.module_a":"./libModuleA.so","providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} }, { "test": "instantiate a client from module-a", "input": {"libraries":{"module_a":"./libModuleA.so"},"clients":[{"name":"my_client","type":"module_a"}]}, - "output": {"abt_io":[],"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} } ] diff --git a/tests/spack.yaml b/tests/spack.yaml index 3d9bb6a..dfe7058 100644 --- a/tests/spack.yaml +++ b/tests/spack.yaml @@ -11,7 +11,6 @@ spack: - mochi-margo - mochi-thallium - mochi-bedrock-module-api - - mochi-abt-io - mochi-flock - nlohmann-json - nlohmann-json-schema-validator From c86784b9abdf75890860529529291b1942bdd324 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Wed, 4 Sep 2024 12:30:53 +0100 Subject: [PATCH 05/10] removed unnecessary flags in workflows --- .github/workflows/test.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62dee22..ce18686 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: packages: write steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup spack uses: spack/setup-spack@v2.1.1 @@ -44,9 +44,6 @@ jobs: cmake .. -DENABLE_TESTS=ON \ -DENABLE_EXAMPLES=ON \ -DENABLE_MPI=ON \ - -DENABLE_MONA=ON \ - -DENABLE_SSG=ON \ - -DENABLE_ABT_IO=ON \ -DENABLE_PYTHON=ON \ -DCMAKE_BUILD_TYPE=Debug make @@ -65,9 +62,6 @@ jobs: -DENABLE_TESTS=ON \ -DENABLE_EXAMPLES=ON \ -DENABLE_MPI=ON \ - -DENABLE_MONA=ON \ - -DENABLE_SSG=ON \ - -DENABLE_ABT_IO=ON \ -DENABLE_PYTHON=ON \ -DCMAKE_BUILD_TYPE=Debug make From 224e6a101e645eff756dc09efe2c1375eac84a91 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Thu, 5 Sep 2024 12:32:49 +0100 Subject: [PATCH 06/10] huge refactoring to get rid of clients and use bedrock-module-api 0.2 --- CMakeLists.txt | 2 +- build.sh | 2 +- examples/CMakeLists.txt | 2 +- examples/module-a.c | 110 ------- examples/module-a.cpp | 53 +++ examples/module-b.cpp | 114 +++---- include/bedrock/ClientDescriptor.hpp | 29 -- include/bedrock/ClientManager.hpp | 199 ------------ include/bedrock/DependencyFinder.hpp | 58 +--- include/bedrock/Jx9Manager.hpp | 2 - include/bedrock/MargoManager.hpp | 4 +- include/bedrock/ProviderHandle.hpp | 22 ++ include/bedrock/ProviderManager.hpp | 30 -- include/bedrock/Server.hpp | 10 +- include/bedrock/ServiceHandle.hpp | 3 +- python/mochi/bedrock/bedrockctl/__main__.py | 3 - python/mochi/bedrock/bedrockctl/client.py | 104 ------ python/mochi/bedrock/client.py | 14 +- python/mochi/bedrock/config_space.py | 38 ++- python/mochi/bedrock/server.py | 66 +--- python/mochi/bedrock/spec.py | 225 +++---------- python/mochi/bedrock/test_client_manager.py | 89 ------ python/mochi/bedrock/test_config_space.py | 9 +- python/mochi/bedrock/test_dependencies.py | 240 +------------- python/mochi/bedrock/test_provider_manager.py | 13 +- python/mochi/bedrock/test_server.py | 2 +- .../bedrock/test_service_group_handle.py | 39 +-- python/mochi/bedrock/test_service_handle.py | 50 +-- python/src/py-bedrock-client.cpp | 16 +- python/src/py-bedrock-server.cpp | 34 -- src/CMakeLists.txt | 1 - src/ClientManager.cpp | 302 ------------------ src/ClientManagerImpl.hpp | 168 ---------- src/DependencyFinder.cpp | 204 ++++-------- src/DependencyFinderImpl.hpp | 7 +- src/MargoManager.cpp | 276 +++++----------- src/MargoManagerImpl.hpp | 50 +-- src/ProviderManager.cpp | 212 ++++-------- src/ProviderManagerImpl.hpp | 84 ++--- src/Server.cpp | 52 +-- src/ServerImpl.hpp | 9 +- src/ServiceHandle.cpp | 4 +- tests/Client.cpp | 21 +- tests/InitInvalid.cpp | 1 + tests/InitJx9.cpp | 1 + tests/InvalidConfigs.json | 88 +---- tests/ValidConfigs.json | 24 +- tests/modules/BaseModule.hpp | 55 +--- tests/modules/Helpers.hpp | 67 +--- tests/modules/ModuleA.cpp | 8 +- tests/modules/ModuleB.cpp | 8 +- tests/modules/ModuleC.cpp | 81 +++-- 52 files changed, 698 insertions(+), 2607 deletions(-) delete mode 100644 examples/module-a.c create mode 100644 examples/module-a.cpp delete mode 100644 include/bedrock/ClientDescriptor.hpp delete mode 100644 include/bedrock/ClientManager.hpp create mode 100644 include/bedrock/ProviderHandle.hpp delete mode 100644 python/mochi/bedrock/bedrockctl/client.py delete mode 100644 python/mochi/bedrock/test_client_manager.py delete mode 100644 src/ClientManager.cpp delete mode 100644 src/ClientManagerImpl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index de7907e..31f8941 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # See COPYRIGHT in top-level directory. cmake_minimum_required (VERSION 3.8) project (bedrock C CXX) -set (CMAKE_CXX_STANDARD 14) +set (CMAKE_CXX_STANDARD 17) set (CMAKE_CXX_STANDARD_REQUIRED ON) enable_testing () diff --git a/build.sh b/build.sh index 95bace3..c13ae14 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/bin/bash SCRIPT_DIR=$(dirname "$0") -cmake $SCRIPT_DIR -DENABLE_TESTS=ON -DENABLE_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_PYTHON=ON -DENABLE_MPI=ON -DENABLE_MONA=ON -DENABLE_SSG=ON -DENABLE_ABT_IO=ON -DENABLE_FLOCK=ON +cmake $SCRIPT_DIR -DENABLE_TESTS=ON -DENABLE_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_PYTHON=ON -DENABLE_MPI=ON -DENABLE_FLOCK=ON diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 0c52dcc..ee478a8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,7 @@ add_executable (example-client ${CMAKE_CURRENT_SOURCE_DIR}/client.cpp) target_link_libraries (example-client bedrock-client) -add_library (example-module-a ${CMAKE_CURRENT_SOURCE_DIR}/module-a.c) +add_library (example-module-a ${CMAKE_CURRENT_SOURCE_DIR}/module-a.cpp) target_include_directories (example-module-a PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include) target_link_libraries (example-module-a bedrock::module-api) diff --git a/examples/module-a.c b/examples/module-a.c deleted file mode 100644 index 958360d..0000000 --- a/examples/module-a.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#include -#include -#include - -static int module_a_register_provider( - bedrock_args_t args, - bedrock_module_provider_t* provider) -{ - margo_instance_id mid = bedrock_args_get_margo_instance(args); - uint16_t provider_id = bedrock_args_get_provider_id(args); - ABT_pool pool = bedrock_args_get_pool(args); - const char* config = bedrock_args_get_config(args); - const char* name = bedrock_args_get_name(args); - - *provider = strdup("module_a:provider"); - printf("Registered a provider from module A\n"); - printf(" -> mid = %p\n", (void*)mid); - printf(" -> provider id = %d\n", provider_id); - printf(" -> pool = %p\n", (void*)pool); - printf(" -> config = %s\n", config); - printf(" -> name = %s\n", name); - return BEDROCK_SUCCESS; -} - -static int module_a_deregister_provider( - bedrock_module_provider_t provider) -{ - free(provider); - printf("Deregistered a provider from module A\n"); - return BEDROCK_SUCCESS; -} - -static char* module_a_get_provider_config( - bedrock_module_provider_t provider) { - (void)provider; - return strdup("{}"); -} - -static int module_a_init_client( - bedrock_args_t args, - bedrock_module_client_t* client) -{ - margo_instance_id mid = bedrock_args_get_margo_instance(args); - *client = strdup("module_a:client"); - printf("Registered a client from module A\n"); - printf(" -> mid = %p\n", (void*)mid); - return BEDROCK_SUCCESS; -} - -static int module_a_finalize_client( - bedrock_module_client_t client) -{ - free(client); - printf("Finalized a client from module A\n"); - return BEDROCK_SUCCESS; -} - -static char* module_a_get_client_config( - bedrock_module_provider_t provider) { - (void)provider; - return strdup("{}"); -} - -static int module_a_create_provider_handle( - bedrock_module_client_t client, - hg_addr_t address, - uint16_t provider_id, - bedrock_module_provider_handle_t* ph) -{ - (void)client; - (void)address; - (void)provider_id; - *ph = strdup("module_a:provider_handle"); - printf("Created provider handle from module A\n"); - return BEDROCK_SUCCESS; -} - -static int module_a_destroy_provider_handle( - bedrock_module_provider_handle_t ph) -{ - free(ph); - printf("Destroyed provider handle from module A\n"); - return BEDROCK_SUCCESS; -} - -static struct bedrock_dependency client_dependencies[] = { - { "some_group", "ssg", BEDROCK_OPTIONAL }, - BEDROCK_NO_MORE_DEPENDENCIES -}; - -static struct bedrock_module_v1 module_a = { - .api_version = 1, - .register_provider = module_a_register_provider, - .deregister_provider = module_a_deregister_provider, - .get_provider_config = module_a_get_provider_config, - .init_client = module_a_init_client, - .finalize_client = module_a_finalize_client, - .get_client_config = module_a_get_client_config, - .create_provider_handle = module_a_create_provider_handle, - .destroy_provider_handle = module_a_destroy_provider_handle, - .provider_dependencies = NULL, - .client_dependencies = client_dependencies -}; - -BEDROCK_REGISTER_MODULE_WITH_VERSION(module_a, module_a, 1) diff --git a/examples/module-a.cpp b/examples/module-a.cpp new file mode 100644 index 0000000..3457c7e --- /dev/null +++ b/examples/module-a.cpp @@ -0,0 +1,53 @@ +/* + * (C) 2020 The University of Chicago + * + * See COPYRIGHT in top-level directory. + */ +#include +#include + +struct ActualProviderA {}; + +class ComponentA : public bedrock::AbstractComponent { + + ActualProviderA* m_provider = nullptr; + + public: + + ComponentA() + : m_provider{new ActualProviderA{}} {} + + ~ComponentA() { + delete m_provider; + } + + static std::shared_ptr + Register(const bedrock::ComponentArgs& args) { + std::cout << "Registering a ComponentA" << std::endl; + std::cout << " -> mid = " << (void*)args.engine.get_margo_instance() << std::endl; + std::cout << " -> provider id = " << args.provider_id << std::endl; + std::cout << " -> config = " << args.config << std::endl; + std::cout << " -> name = " << args.name << std::endl; + std::cout << " -> tags = "; + for(auto& t : args.tags) std::cout << t << " "; + std::cout << std::endl; + auto pool_it = args.dependencies.find("pool"); + auto pool = pool_it->second[0]->getHandle(); + return std::make_shared(); + } + + static std::vector + GetDependencies(const bedrock::ComponentArgs& args) { + (void)args; + std::vector deps = { + { "pool", "pool", true, false, false } + }; + return deps; + } + + void* getHandle() override { + return static_cast(m_provider); + } +}; + +BEDROCK_REGISTER_COMPONENT_TYPE(module_a, ComponentA) diff --git a/examples/module-b.cpp b/examples/module-b.cpp index b815fa8..c6f019d 100644 --- a/examples/module-b.cpp +++ b/examples/module-b.cpp @@ -3,87 +3,67 @@ * * See COPYRIGHT in top-level directory. */ -#include +#include #include -class ServiceBFactory : public bedrock::AbstractServiceFactory { +struct ActualProviderA; - public: - - ServiceBFactory() { - m_provider_dependencies.push_back({ - "ssg_group", "ssg", BEDROCK_REQUIRED }); - m_provider_dependencies.push_back({ - "mona_instance", "mona", BEDROCK_REQUIRED }); - m_provider_dependencies.push_back({ - "a_provider", "module_a", BEDROCK_REQUIRED | BEDROCK_KIND_PROVIDER}); - m_provider_dependencies.push_back({ - "a_provider_handle", "module_a", BEDROCK_REQUIRED | BEDROCK_ARRAY | BEDROCK_KIND_PROVIDER_HANDLE}); - m_provider_dependencies.push_back({ - "a_client", "module_a", BEDROCK_REQUIRED | BEDROCK_KIND_CLIENT}); - } - - void* registerProvider(const bedrock::FactoryArgs& args) override { - std::cout << "Registering a provider from module B" << std::endl; - std::cout << " -> mid = " << (void*)args.mid << std::endl; - std::cout << " -> provider_id = " << args.provider_id << std::endl; - std::cout << " -> pool = " << (void*)args.pool << std::endl; - std::cout << " -> config = " << args.config << std::endl; - std::cout << " -> name = " << args.name << std::endl; - return (void*)0x1; - } - - void deregisterProvider(void* provider) override { - (void)provider; - std::cout << "Deregistring provider from module B" << std::endl; - } +struct ActualProviderB {}; - std::string getProviderConfig(void* provider) override { - (void)provider; - return "{}"; - } +class ComponentB : public bedrock::AbstractComponent { - void* initClient(const bedrock::FactoryArgs& args) override { - (void)args; - std::cout << "Initializing client from module B" << std::endl; - return (void*)0x2; - } + ActualProviderB* m_provider = nullptr; - void finalizeClient(void* client) override { - (void)client; - std::cout << "Finalizing client from module B" << std::endl; - } + public: - std::string getClientConfig(void* client) override { - (void)client; - return "{}"; - } + ComponentB() + : m_provider{new ActualProviderB{}} {} - void* createProviderHandle(void* client, hg_addr_t address, uint16_t provider_id) override { - (void)client; - (void)address; - (void)provider_id; - std::cout << "Creating a provider handle from module B" << std::endl; - return (void*)0x3; + ~ComponentB() { + delete m_provider; } - void destroyProviderHandle(void* providerHandle) override { - (void)providerHandle; - std::cout << "Destroying provider handle from module B" << std::endl; + static std::shared_ptr + Register(const bedrock::ComponentArgs& args) { + std::cout << "Registering a ComponentA" << std::endl; + std::cout << " -> mid = " << (void*)args.engine.get_margo_instance() << std::endl; + std::cout << " -> provider id = " << args.provider_id << std::endl; + std::cout << " -> config = " << args.config << std::endl; + std::cout << " -> name = " << args.name << std::endl; + std::cout << " -> tags = "; + for(auto& t : args.tags) std::cout << t << " "; + std::cout << std::endl; + auto pool_it = args.dependencies.find("pool"); + auto pool = pool_it->second[0]->getHandle(); + std::cout << " -> pool = " << pool.native_handle() << std::endl; + auto a_provider_it = args.dependencies.find("a_provider"); + auto a_provider_comp_handle = a_provider_it->second[0]->getHandle(); + auto a_provider = a_provider_comp_handle->getHandle(); + std::cout << " -> a_provider = " << a_provider << std::endl; + auto a_ph_it = args.dependencies.find("a_provider_handles"); + int i = 0; + for(auto& p : a_ph_it->second) { + auto ph = p->getHandle(); + std::cout << " -> a_provider_handles[" << i << "] = " << + static_cast(ph) << " with provider id " << ph.provider_id() << std::endl; + } + return std::make_shared(); } - const std::vector& getProviderDependencies() override { - return m_provider_dependencies; + static std::vector + GetDependencies(const bedrock::ComponentArgs& args) { + (void)args; + std::vector deps = { + { "pool", "pool", true, false, false }, + { "a_provider", "module_a", true, false, false }, + { "a_provider_handles", "module_a", false, true, false } + }; + return deps; } - const std::vector& getClientDependencies() override { - return m_client_dependencies; + void* getHandle() override { + return static_cast(m_provider); } - - private: - - std::vector m_provider_dependencies; - std::vector m_client_dependencies; }; -BEDROCK_REGISTER_MODULE_FACTORY(module_b, ServiceBFactory) +BEDROCK_REGISTER_COMPONENT_TYPE(module_a, ComponentB) diff --git a/include/bedrock/ClientDescriptor.hpp b/include/bedrock/ClientDescriptor.hpp deleted file mode 100644 index c26698b..0000000 --- a/include/bedrock/ClientDescriptor.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_CLIENT_DESC_HPP -#define __BEDROCK_CLIENT_DESC_HPP - -#include -#include - -namespace bedrock { - -class AbstractServiceFactory; - -/** - * @brief A ClientDescriptor is an object that describes a client. - */ -struct ClientDescriptor { - - std::string name; // name of the client - std::string type; // name of the module - - template void serialize(A& ar) { ar(name, type); } -}; - -} // namespace bedrock - -#endif diff --git a/include/bedrock/ClientManager.hpp b/include/bedrock/ClientManager.hpp deleted file mode 100644 index bdc971d..0000000 --- a/include/bedrock/ClientManager.hpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * (C) 2021 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_CLIENT_MANAGER_HPP -#define __BEDROCK_CLIENT_MANAGER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace bedrock { - -class ClientManagerImpl; -class Server; -class ServerImpl; -class DependencyFinder; -class Jx9Manager; - -/** - * @brief A ClientManager is a Bedrock provider that manages - * a list of clients and uses the ModuleContext to create new ones - * from configuration files. - */ -class ClientManager { - - friend class Server; - friend class DependencyFinder; - friend class ClientManagerImpl; - friend class ServerImpl; - - using json = nlohmann::json; - - public: - /** - * @brief Constructor. - * - * @param margo Margo context - * @param jx9 Jx9 manager - * @param provider_id Provider id used by this client manager - * @param pool Pool in which to execute RPCs looking up clients - */ - ClientManager(const MargoManager& margo, const Jx9Manager& jx9, - uint16_t provider_id, - const std::shared_ptr& pool); - - /** - * @brief Copy-constructor. - */ - ClientManager(const ClientManager&); - - /** - * @brief Move-constructor. - */ - ClientManager(ClientManager&&); - - /** - * @brief Copy-assignment operator. - */ - ClientManager& operator=(const ClientManager&); - - /** - * @brief Move-assignment operator. - */ - ClientManager& operator=(ClientManager&&); - - /** - * @brief Destructor. - */ - ~ClientManager(); - - /** - * @brief Checks whether the ClientManager instance is valid. - */ - operator bool() const; - - /** - * @brief Set the DependencyFinder object to use to resolve dependencies. - * - * @param finder DependencyFinder - */ - void setDependencyFinder(const DependencyFinder& finder); - - /** - * @brief Get an internal client instance by its name. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the client instance. - */ - std::shared_ptr - getClient(const std::string& name) const; - - /** - * @brief Get an internal client instance by its index. - * If not found, this function will throw an Exception. - * If returned, the shared_ptr is guaranteed not to be null. - * - * @return a NamedDependency representing the client instance. - */ - std::shared_ptr - getClient(size_t index) const; - - /** - * @brief Find any client of a certain type. If none is found, - * create such a client. This function will throw an exception - * if the client could not be found nor created. - * - * @param [in] type Type of client to lookup - * @param [out] wrapper Resulting client wrapper - */ - std::shared_ptr - getOrCreateAnonymous(const std::string& type); - - /** - * @brief Return the number of clients. - */ - size_t numClients() const; - - /** - * @brief Create a client. - * - * @param name Name of the client. - * @param type Type of the client. - * @param config JSON configuration for the client. - * @param dependencies Dependency map. - * @param tags Tags. - */ - std::shared_ptr - addClient(const std::string& name, - const std::string& type, - const json& config, - const ResolvedDependencyMap& dependencies, - const std::vector& tags = {}); - - /** - * @brief Destroy a client. - * - * @param name Name of the client. - */ - void removeClient(const std::string& name); - - /** - * @brief Destroy a client. - * - * @param index Index.. - */ - void removeClient(size_t index); - - /** - * @brief Add a client from a full JSON description. The description should - * be of the following form: - * - * { - * "type" : "remi", - * "name" : "my_remi_client", - * "dependencies" : { - * "abt_io" : "my_abt_io" - * }, - * "config" : { ... }, - * "tage" : [ "tag1", "tag2", ... ] - * } - * - * @param jsonString JSON string. - */ - std::shared_ptr - addClientFromJSON(const json& description); - - /** - * @brief Add a list of providers represented by a JSON array. - * The JSON array entries must follow the format expected by - * addClientFromJSON. - * - * @param jsonString JSON string. - */ - void addClientListFromJSON(const json& list); - - /** - * @brief Return the current JSON configuration. - */ - json getCurrentConfig() const; - - private: - std::shared_ptr self; - - inline operator std::shared_ptr() const { return self; } - - inline ClientManager(std::shared_ptr impl) - : self(std::move(impl)) {} -}; - -} // namespace bedrock - -#endif diff --git a/include/bedrock/DependencyFinder.hpp b/include/bedrock/DependencyFinder.hpp index b557a83..147de07 100644 --- a/include/bedrock/DependencyFinder.hpp +++ b/include/bedrock/DependencyFinder.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -18,7 +17,6 @@ namespace bedrock { class Server; class ServerImpl; class ProviderManager; -class ClientManager; class DependencyFinderImpl; /** @@ -29,7 +27,6 @@ class DependencyFinder { friend class Server; friend class ProviderManager; - friend class ClientManager; friend class ServerImpl; public: @@ -38,12 +35,10 @@ class DependencyFinder { * @param mpi MPI context * @param margo Margo context * @param pmanager Provider manager - * @param cmanager Client manager */ DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, - const ProviderManager& pmanager, - const ClientManager& cmanager); + const ProviderManager& pmanager); /** * @brief Copy-constructor. @@ -95,20 +90,19 @@ class DependencyFinder { * * For instance, "abc" represents the name "abc". * "abc:123" represents a provider of type "abc" with - * provider id 123. "abc->def@address" represents a provider handle - * created from client named "abc", pointing to a provider named "def" - * at address "address". + * provider id 123. "abc@address" represents a provider handle + * pointing to a provider named "abc" at address "address". * * @param [in] type Type of dependency. - * @param [in] kind Kind of dependency (BEDROCK_KIND_*). * @param [in] spec Specification string. * @param [out] Resolved specification. * * @return handle to dependency */ std::shared_ptr - find(const std::string& type, int32_t kind, - const std::string& spec, std::string* resolved) const; + find(const std::string& type, + const std::string& spec, + std::string* resolved) const; /** * @brief Find a local provider based on a type and provider id. @@ -120,7 +114,8 @@ class DependencyFinder { * @return An abstract pointer to the dependency. */ std::shared_ptr findProvider( - const std::string& type, uint16_t provider_id) const; + const std::string& type, + uint16_t provider_id) const; /** * @brief Find a local provider based on a name. @@ -133,35 +128,15 @@ class DependencyFinder { * @return An abstract pointer to the dependency. */ std::shared_ptr findProvider( - const std::string& type, const std::string& name, + const std::string& type, + const std::string& name, uint16_t* provider_id = nullptr) const; - /** - * @brief Find client with a given name. The returned - * handle will remain valid until the program terminates. - * If the name is empty, this function will try to find - * a client of the specified type. - * - * @param type Type of client. - * @param name Name of the client. - * @param create_if_not_found Create the client if not found. - * @param found_name name of the client found or create. - * - * @return An abstract pointer to the dependency. - */ - std::shared_ptr findClient( - const std::string& type, const std::string& name) const; - /** * @brief Make a provider handle to a specified provider. * Throws an exception if no provider was found with this * provider id at the specified location. - * The returned VoidPtr object owns the underlying provider - * handle, so the caller is responsible for copying it if - * necessary. * - * @param client_name Name of the client to use (or "" for any client of the - * right type) * @param type Type of service. * @param provider_id Provider id * @param locator Location (e.g. "local" or mercury address) @@ -170,8 +145,8 @@ class DependencyFinder { * @return An abstract pointer to the dependency. */ std::shared_ptr - makeProviderHandle(const std::string& client_name, - const std::string& type, uint16_t provider_id, + makeProviderHandle(const std::string& type, + uint16_t provider_id, const std::string& locator, std::string* resolved) const; @@ -179,12 +154,7 @@ class DependencyFinder { * @brief Make a provider handle to a specified provider. * Throws an exception if no provider was found with this * provider name at the specified location. - * The returned VoidPtr object owns the underlying provider - * handle, so the caller is responsible for copying it if - * necessary. * - * @param client_name Name of the client to use (or "" for any client of the - * right type) * @param type Type of service. * @param name Name of the provider * @param locator Location (e.g. "local" or mercury addresses) @@ -193,8 +163,8 @@ class DependencyFinder { * @return An abstract pointer to the dependency. */ std::shared_ptr makeProviderHandle( - const std::string& client_name, - const std::string& type, const std::string& name, + const std::string& type, + const std::string& name, const std::string& locator, std::string* resolved) const; diff --git a/include/bedrock/Jx9Manager.hpp b/include/bedrock/Jx9Manager.hpp index 5f60059..5156b02 100644 --- a/include/bedrock/Jx9Manager.hpp +++ b/include/bedrock/Jx9Manager.hpp @@ -17,7 +17,6 @@ namespace bedrock { class Server; class ServerImpl; class Jx9ManagerImpl; -class ClientManager; class ProviderManager; /** @@ -27,7 +26,6 @@ class Jx9Manager { friend class Server; friend class ServerImpl; - friend class ClientManager; friend class ProviderManager; public: diff --git a/include/bedrock/MargoManager.hpp b/include/bedrock/MargoManager.hpp index dee16e9..74bea4b 100644 --- a/include/bedrock/MargoManager.hpp +++ b/include/bedrock/MargoManager.hpp @@ -16,7 +16,6 @@ namespace tl = thallium; class Server; class ProviderManager; -class ClientManager; class DependencyFinder; class MargoManagerImpl; class ProviderEntry; @@ -29,7 +28,6 @@ class MargoManager { friend class Server; friend class ProviderManager; - friend class ClientManager; friend class DependencyFinder; friend class ProviderEntry; friend class ServerImpl; @@ -94,7 +92,7 @@ class MargoManager { * * @return reference to the thallium engine. */ - tl::engine getThalliumEngine() const; + const tl::engine& getThalliumEngine() const; /** * @brief Get the default handle pool from Margo. diff --git a/include/bedrock/ProviderHandle.hpp b/include/bedrock/ProviderHandle.hpp new file mode 100644 index 0000000..5115b6c --- /dev/null +++ b/include/bedrock/ProviderHandle.hpp @@ -0,0 +1,22 @@ +/* + * (C) 2020 The University of Chicago + * + * See COPYRIGHT in top-level directory. + */ +#ifndef __BEDROCK_PROVIDER_HANDLE_H +#define __BEDROCK_PROVIDER_HANDLE_H + +#include + +namespace bedrock { + +/** + * @brief A pointer to a ProviderHandle is returned by + * DependencyFinder::makeProviderHandle, wrapped as a + * std::shared_ptr. + */ +using ProviderHandle = thallium::provider_handle; + +} // namespace bedrock + +#endif diff --git a/include/bedrock/ProviderManager.hpp b/include/bedrock/ProviderManager.hpp index 7f167a4..97965da 100644 --- a/include/bedrock/ProviderManager.hpp +++ b/include/bedrock/ProviderManager.hpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -130,26 +129,6 @@ class ProviderManager { std::shared_ptr lookupProvider(const std::string& spec) const; - /** - * @brief Register a provider from a descriptor. - * - * @param name Name of the provider. - * @param type Type of provider. - * @param provider_id Provider ID. - * @param pool Pool. - * @param config JSON configuration for the provider. - * @param dependencies Dependency map. - * @param tags Tags. - */ - std::shared_ptr - registerProvider(const std::string& name, - const std::string& type, - uint16_t provider_id, - std::shared_ptr pool, - const json& config, - const ResolvedDependencyMap& dependencies, - const std::vector& tags = {}); - /** * @brief Deregister a provider from a specification. The specification has * the same format as in lookupProvider(). @@ -185,15 +164,6 @@ class ProviderManager { */ void addProviderListFromJSON(const json& list); - /** - * @brief Change the pool associated with a provider. - * - * @param provider Provider. - * @param pool New pool. - */ - void changeProviderPool(const std::string& provider, - const std::string& pool); - /** * @brief Migrates the specified provider state to the destination. * diff --git a/include/bedrock/Server.hpp b/include/bedrock/Server.hpp index 01fa818..ec2e610 100644 --- a/include/bedrock/Server.hpp +++ b/include/bedrock/Server.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -88,11 +87,6 @@ class Server { */ ProviderManager getProviderManager() const; - /** - * @brief Get the underlying ClientManager. - */ - ClientManager getClientManager() const; - /** * @brief Blocks until the underlying margo instance is finalized. */ @@ -111,8 +105,8 @@ class Server { private: std::unique_ptr self; - static void onFinalize(void* uargs); - static void onPreFinalize(void* uargs); + void onFinalize(); + void onPreFinalize(); }; } // namespace bedrock diff --git a/include/bedrock/ServiceHandle.hpp b/include/bedrock/ServiceHandle.hpp index 6551fd7..e0a742a 100644 --- a/include/bedrock/ServiceHandle.hpp +++ b/include/bedrock/ServiceHandle.hpp @@ -80,11 +80,10 @@ class ServiceHandle { /** * @brief Ask the remote service daemon to load a module library. * - * @param name Name of the module. * @param path Library path. * @param req Asynchronous request to wait on, if provided. */ - void loadModule(const std::string& name, const std::string& path, + void loadModule(const std::string& path, AsyncRequest* req = nullptr) const; /** diff --git a/python/mochi/bedrock/bedrockctl/__main__.py b/python/mochi/bedrock/bedrockctl/__main__.py index 0ec0880..cdec62e 100644 --- a/python/mochi/bedrock/bedrockctl/__main__.py +++ b/python/mochi/bedrock/bedrockctl/__main__.py @@ -18,9 +18,6 @@ from .provider import app as provider_app app.add_typer(provider_app, name="provider", help="Access and modify providers") -from .client import app as client_app -app.add_typer(client_app, name="client", help="Access and modify clients") - @app.command() def status(): diff --git a/python/mochi/bedrock/bedrockctl/client.py b/python/mochi/bedrock/bedrockctl/client.py deleted file mode 100644 index bb5aa72..0000000 --- a/python/mochi/bedrock/bedrockctl/client.py +++ /dev/null @@ -1,104 +0,0 @@ -import typer -from typing_extensions import Annotated -from enum import Enum -from typing import Optional, List -from ..spec import PoolSpec -from ..client import ClientException - - -app = typer.Typer() - - -@app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True}) -def create( - ctx: typer.Context, - name: Annotated[ - str, typer.Argument(help="Name of the client to create")], - type: Annotated[ - str, typer.Option( - "-t", "--type", help="Type of client")], - dependencies: Annotated[ - List[str], typer.Option( - "-d", "--dependency", help="Dependency in the form \"name:value\"")] = [], - tags: Annotated[ - List[str], typer.Option( - "-a", "--tag", help="Tag")] = [], - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Create a new client in the target Bedrock process(es). - """ - from ._util import parse_config_from_args - config = parse_config_from_args(ctx.args) - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import parse_dependencies - dependencies = parse_dependencies(dependencies) - client = { - "name": name, - "type": type, - "config": config, - "dependencies": dependencies, - "tags": tags - } - from ._util import ServiceContext - with ServiceContext(target) as service: - for i in range(len(service)): - if not rank_is_in(i, ranks): - continue - try: - service[i].add_client(client) - except ClientException as e: - print(f"Error adding client in {service[i].address}: {str(e)}") - del service - - -@app.command() -def list(target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Lists the clients in each of the target Bedrock process(es). - """ - from ._util import parse_target_ranks, rank_is_in - ranks = parse_target_ranks(ranks) - from ._util import ServiceContext - from rich import print - with ServiceContext(target) as service: - config = { a: c["clients"] for a, c in service.config.items() } - for i in range(len(service)): - if not rank_is_in(i, ranks): - del config[service[i].address] - print(config) - del service - - -@app.command() -def remove( - name: Annotated[ - str, typer.Argument(help="Name of the client to remove")], - target: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Target addresses or group file")] = None, - ranks: Annotated[ - Optional[str], typer.Option(hidden=True, - help="Comma-separated list of ranks")] = None - ): - """ - Remove a client from the target Bedrock process(es). - """ - print("This command is not implemented yet") - raise typer.Exit(code=-1) - - -if __name__ == "__main__": - app() diff --git a/python/mochi/bedrock/client.py b/python/mochi/bedrock/client.py index 3e6890e..8bf9345 100644 --- a/python/mochi/bedrock/client.py +++ b/python/mochi/bedrock/client.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo import json -from .spec import ProcSpec, XstreamSpec, PoolSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, XstreamSpec, PoolSpec, ProviderSpec ClientException = pybedrock_client.Exception @@ -51,8 +51,8 @@ def spec(self): def query(self, script: str): return json.loads(self._internal.query_config(script)) - def load_module(self, name: str, path: str): - self._internal.load_module(name, path) + def load_module(self, path: str): + self._internal.load_module(path) def _ensure_config_str(self, config): if isinstance(config, str): @@ -76,18 +76,10 @@ def add_xstream(self, config: str|dict|XstreamSpec): def remove_xstream(self, name: str): self._internal.remove_xstream(name) - def add_client(self, description: str|dict|ClientSpec): - description = self._ensure_config_str(description) - self._internal.add_client(description) - def add_provider(self, description: str|dict|ProviderSpec): description = self._ensure_config_str(description) return self._internal.add_provider(description) - def change_provider_pool(self, provider_name: str, pool_name: str): - self._internal.change_provider_pool( - provider_name, pool_name) - class ServiceGroupHandle: diff --git a/python/mochi/bedrock/config_space.py b/python/mochi/bedrock/config_space.py index cb21006..1de4afb 100644 --- a/python/mochi/bedrock/config_space.py +++ b/python/mochi/bedrock/config_space.py @@ -17,7 +17,7 @@ from ConfigSpace.hyperparameters import Hyperparameter from ConfigSpace.conditions import Condition, Conjunction, ConditionLike from ConfigSpace.forbidden import ForbiddenLike -from typing import Sequence, Any +from typing import Sequence, Any, Mapping, Hashable # Configuration @@ -33,6 +33,7 @@ Constant = ConfigSpace.Constant UnParametrizedHyperparameter = ConfigSpace.UnParametrizedHyperparameter OrdinalHyperparameter = ConfigSpace.OrdinalHyperparameter +IntegerHyperparameter = ConfigSpace.hyperparameters.IntegerHyperparameter # Conditions AndConjunction = ConfigSpace.AndConjunction OrConjunction = ConfigSpace.OrConjunction @@ -68,9 +69,13 @@ def __init__(self, name: str|None = None, self._conditions = {} # associates the name of the condition's child to the tuple # (condition_type, parent_name, value) - def add(self, arg: (Hyperparameter|ConditionLike|ForbiddenLike)): + def add(self, arg: (Hyperparameter|ConditionLike|ForbiddenLike|list)): if self._frozen: raise PermissionError("ConfigurationSpace is already frozen") + if isinstance(arg, list): + for x in arg: + self.add(x) + return if isinstance(arg, Condition): if arg.child.name not in self._conditions: self._conditions[arg.child.name] = [] @@ -209,3 +214,32 @@ def FloatOrConst(name: str, bounds: float|tuple[float, float], *, else: return Float(name=name, bounds=bounds, distribution=distribution, default=default, log=log, meta=meta) + + +def CategoricalChoice(name: str, + num_options: IntegerHyperparameter|int, + weights: Sequence[float] | None = None, + meta: Mapping[Hashable, Any] | None = None) -> list[Any]: + """ + This function is a helper to build a Categorical hyperparameter with the specified + name, whose value must be taken between 0 and num_options-1. num_options can be either + and integer or an IntegerHyperparameter. In the later case, this function will also + construct the required Forbidden clauses to constrain the value of the choice. + + The result of this function is a list of Hyperparameter and Forbidden clauses, which + should then be passed to a ConfigurationSpace's add function. + """ + + max_options = num_options if isinstance(num_options, int) else int(num_options.upper) + min_options = num_options if isinstance(num_options, int) else int(num_options.lower) + choice = CategoricalOrConst(name, list(range(max_options)), + default=0, meta=meta, weights=weights) + conditions = [] + if max_options != min_options: + for j in range(min_options, max_options): + conditions.append( + ForbiddenAndConjunction( + ForbiddenEqualsClause(num_options, j), + ForbiddenInClause(choice, list(range(j, max_options))))) + return [choice, *conditions] + diff --git a/python/mochi/bedrock/server.py b/python/mochi/bedrock/server.py index a6e2948..599d878 100644 --- a/python/mochi/bedrock/server.py +++ b/python/mochi/bedrock/server.py @@ -16,7 +16,7 @@ import pymargo.core import pymargo from typing import Mapping, List -from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, ProviderSpec, ClientSpec +from .spec import ProcSpec, MargoSpec, PoolSpec, XstreamSpec, ProviderSpec import json @@ -41,14 +41,9 @@ def name(self): def type(self): return self._internal.type - @property - def handle(self): - return self._internal.handle - Pool = NamedDependency Xstream = NamedDependency -Client = NamedDependency class ProviderDependency(NamedDependency): @@ -162,54 +157,6 @@ def default_handler_pool(self): return Pool(self._internal.default_handler_pool) -class ClientManager: - - def __init__(self, internal: pybedrock_server.ClientManager, server: 'Server'): - self._internal = internal - self._server = server - - @property - def config(self) -> dict: - return self._internal.config - - @property - def spec(self) -> list[ClientSpec]: - return [ClientSpec.from_dict(client) for client in self.config] - - def __len__(self): - return self._internal.num_clients - - def __getitem__(self, key: int|str) -> Client: - return self._internal.get_client(key) - - def __delitem__(self, key: int|str) -> None: - self._internal.remove_client(key) - - def __contains__(self, key: str) -> bool: - try: - self.__getitem__(key) - return True - except BedrockException: - return False - - def get_or_create_anonymous(self, type: str) -> Client: - return Client(self._internal.get_client_or_create(type)) - - def create(self, name: str, type: str, config: str|dict = "{}", - dependencies: dict[str,str|list[str]] = {}, - tags: list[str] = []) -> Client: - if isinstance(config, str): - config = json.loads(config) - info = { - "name": name, - "type": type, - "dependencies": dependencies, - "tags": tags, - "config": config - } - return Client(self._internal.add_client(info)) - - class ProviderManager: def __init__(self, internal: pybedrock_server.ProviderManager, server: 'Server'): @@ -223,7 +170,7 @@ def config(self) -> dict: @property def spec(self) -> list[ProviderSpec]: abt_spec = self._server.margo.spec.argobots - return [ProviderSpec.from_dict(provider, abt_spec) for provider in self.config] + return [ProviderSpec.from_dict(provider) for provider in self.config] def __len__(self): return self._internal.num_providers @@ -245,11 +192,8 @@ def lookup(self, locator: str): return Provider(self, self._internal.lookup_provider(locator)) def create(self, name: str, type: str, provider_id: int = 65535, - pool: str|int|Pool = "__primary__", config: str|dict = {}, dependencies: dict[str,str|list[str]] = {}, - tags: list[str] = []) -> Client: - if isinstance(pool, Pool): - pool = pool.name + tags: list[str] = []) -> Provider: if isinstance(config, str): config = json.loads(config) info = { @@ -324,10 +268,6 @@ def spec(self) -> ProcSpec: def margo(self) -> MargoManager: return MargoManager(self._internal.margo_manager, self) - @property - def clients(self) -> ClientManager: - return ClientManager(self._internal.client_manager, self) - @property def providers(self) -> ProviderManager: return ProviderManager(self._internal.provider_manager, self) diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index 04c86f6..c800121 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -19,6 +19,10 @@ from typing import List, NoReturn, Union, Optional, Sequence, Any, Callable, Mapping +CS = 'ConfigurationSpace' +Config = 'Configuration' + + class _Configurable: """ For some of the classes bellow, initializing from config simply means extracting @@ -27,7 +31,7 @@ class _Configurable: """ @classmethod - def from_config(cls, *, config: 'Configuration', prefix: str = '', **kwargs): + def from_config(cls, *, config: Config, prefix: str = '', **kwargs): expected_attr = set(attribute.name for attribute in cls.__attrs_attrs__) expected_kwargs = { k: v for k, v in kwargs.items() if k in expected_attr} for param, value in config.items(): @@ -461,7 +465,7 @@ def space(*, output_eager_size: int|tuple[int,int] = 4080, na_max_expected_size: int|tuple[int,int] = 0, na_max_unexpected_size: int|tuple[int,int] = 0, - **kwargs): + **kwargs) -> CS: """ Create a ConfigurationSpace object to generate MercurySpecs. Each of the argument can be set to either a single value or a range @@ -556,7 +560,7 @@ def validate(self) -> NoReturn: @staticmethod def space(*, pool_kinds: str|list[str] = ['fifo_wait', 'fifo', 'prio_wait', 'earliest_first'], - **kwargs): + **kwargs) -> CS: """ Create a ConfigurationSpace to generate PoolSpec objects. pool_kinds can be specified as a string or a list of strings to force the pool kind @@ -656,7 +660,7 @@ def validate(self) -> NoReturn: @staticmethod def space(*, scheduler_types: str|list[str] = ['basic_wait', 'default', 'basic', 'prio', 'randws'], - **kwargs): + **kwargs) -> CS: """ Create a ConfigurationSpace to generate SchedulerSpec objects. """ @@ -664,14 +668,6 @@ def space(*, cs = ConfigurationSpace() default_scheduler_types = scheduler_types[0] if isinstance(scheduler_types, list) else scheduler_types cs.add(CategoricalOrConst('type', scheduler_types, default=default_scheduler_types)) - """ - for i in range(0, max_num_pools): - if isinstance(pool_association_weights, list): - weight = pool_association_weights[i] - else: - weight = pool_association_weights - cs.add(FloatOrConst(f'pool_association_weight[{i}]', weight, default=-1.0)) - """ return cs @@ -782,7 +778,7 @@ def validate(self) -> NoReturn: self.scheduler.validate() @staticmethod - def space(*args, **kwargs): + def space(*args, **kwargs) -> CS: """ Create a ConfigurationSpace object from which to generate XstreamSpecs. This function essentially forwards its arguments to the underlying @@ -799,7 +795,7 @@ def space(*args, **kwargs): def from_config(*, name: str, pools: list[PoolSpec], - config: 'Configuration', + config: Config, prefix: str = ''): """ Create an XstreamSpec from a Configuration object. @@ -1010,7 +1006,7 @@ def space(*, pool_kinds : list[str] = ['fifo_wait', 'fifo', 'prio_wait', 'earliest_first'], scheduler_types: str|list[str]|None = ['basic_wait', 'default', 'basic', 'prio', 'randws'], mapping_weight_range: tuple[float,float] = (-1.0, 1.0), - **kwargs): + **kwargs) -> CS: """ Create the ConfigurationSpace of an ArgobotsSpec. @@ -1075,12 +1071,12 @@ def space(*, @staticmethod def from_config(*, - config: 'Configuration', + config: Config, prefix: str = '', pool_name_format: str = '__pool_{}__', xstream_name_format: str = '__xstream_{}__', use_progress_thread: bool = False, - **kwargs): + **kwargs) -> 'ArgobotsSpec': """ Create an ArgobotsSpec from a Configuration object. pool_name_format and xstream_name_format are used to format the names @@ -1298,7 +1294,7 @@ def space(*, progress_timeout_ub_msec: int|tuple[int,int] = 100, use_progress_thread: bool|tuple[bool,bool] = [True, False], rpc_pool: int|tuple[int,int]|None = None, - **kwargs): + **kwargs) -> CS: """ Create the ConfigurationSpace for a MargoSpec. @@ -1316,7 +1312,8 @@ def space(*, IntegerOrConst, ForbiddenAndConjunction, ForbiddenInClause, - ForbiddenEqualsClause) + ForbiddenEqualsClause, + CategoricalChoice) cs = ConfigurationSpace() cs.add(CategoricalOrConst('use_progress_thread', use_progress_thread)) cs.add(IntegerOrConst('handle_cache_size', handle_cache_size)) @@ -1330,20 +1327,11 @@ def space(*, prefix='mercury', delimiter='.', configuration_space=mercury_cs) hp_num_pools = cs['argobots.num_pools'] - # Note: rpc_pool and progress_pool are categorical because AI tools should not - # make the assumption that adding/removing 1 to the value will lead to a smaller - # change than adding/removing a larger value. - hp_rpc_pool = CategoricalOrConst('rpc_pool', list(range(hp_num_pools.upper)), default=0) - cs.add(hp_rpc_pool) - # add conditions on the possible values of rpc_pool and progress_pool - for i in range(hp_num_pools.lower, hp_num_pools.upper): - cs.add(ForbiddenAndConjunction( - ForbiddenInClause(hp_rpc_pool, list(range(i, hp_num_pools.upper))), - ForbiddenEqualsClause(hp_num_pools, i))) + cs.add(CategoricalChoice('rpc_pool', num_options=hp_num_pools)) return cs @staticmethod - def from_config(*, config: 'Configuration', prefix: str = '', **kwargs): + def from_config(*, config: Config, prefix: str = '', **kwargs) -> 'MargoSpec': """ Create a MargoSpec from a Configuration object. @@ -1381,6 +1369,11 @@ def from_config(*, config: 'Configuration', prefix: str = '', **kwargs): **extra) +#ProviderConfigSpaceMaker = Callable[[CS], CS] +#ProviderConfigResolver = Callable[[CS], None] +#ProviderDependencyResolver = Callable[[Config, str], dict] + + @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class ProviderSpec: """Provider specification. @@ -1391,9 +1384,6 @@ class ProviderSpec: :param type: Type of provider :type type: str - :param pool: Pool associated with the group - :type pool: PoolSpec - :param provider_id: Provider id :type provider_id: int @@ -1413,8 +1403,6 @@ class ProviderSpec: type: str = attr.ib( validator=instance_of(str), on_setattr=attr.setters.frozen) - pool: PoolSpec = attr.ib( - validator=instance_of(PoolSpec)) provider_id: int = attr.ib( default=0, validator=instance_of(int)) @@ -1433,27 +1421,19 @@ def to_dict(self) -> dict: """ return {'name': self.name, 'type': self.type, - 'pool': self.pool.name, 'provider_id': self.provider_id, 'dependencies': self.dependencies, 'config': self.config, 'tags': self.tags} @staticmethod - def from_dict(data: dict, abt_spec: ArgobotsSpec) -> 'ProviderSpec': - """Construct a ProviderSpec from a dictionary. Since the dictionary - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. + def from_dict(data: dict) -> 'ProviderSpec': + """Construct a ProviderSpec from a dictionary. :param data: Dictionary :type data: dict - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec """ - args = data.copy() - args['pool'] = abt_spec.pools[data['pool']] - provider = ProviderSpec(**args) + provider = ProviderSpec(**data) return provider def to_json(self, *args, **kwargs) -> str: @@ -1462,33 +1442,25 @@ def to_json(self, *args, **kwargs) -> str: return json.dumps(self.to_dict(), *args, **kwargs) @staticmethod - def from_json(json_string: str, abt_spec: ArgobotsSpec) -> 'ProviderSpec': - """Construct a ProviderSpec from a JSON string. Since the JSON string - references the pool by name or index, an ArgobotsSpec is necessary - to resolve the reference. + def from_json(json_string: str) -> 'ProviderSpec': + """Construct a ProviderSpec from a JSON string. :param json_string: JSON string :type json_string: str - - :param abt_spec: ArgobotsSpec in which to look for the PoolSpec - :type abt_spec: ArgobotsSpec """ - return ProviderSpec.from_dict(json.loads(json_string), abt_spec) + return ProviderSpec.from_dict(json.loads(json_string)) @staticmethod - def space(*, type: str, max_num_pools: int, tags: list[str] = [], - provider_config_space: Optional['ConfigurationSpace'] = None, - provider_config_resolver: Callable[['Configuration', str], dict]|None = None, - dependency_config_space: Optional['ConfigurationSpace'] = None, - dependency_resolver: Callable[['Configuration', str], dict]|None = None): + def space(*, type: str, tags: list[str] = [], + provider_config_space: Optional[CS] = None, + provider_config_resolver: Callable[[Config, str], dict]|None = None, + dependency_config_space: Optional[CS] = None, + dependency_resolver: Callable[[Config, str], dict]|None = None) -> CS: """ Create a ConfigurationSpace for a ProviderSpec. - type: type of provider. - - max_num_pools: maximum number of pools in the underlying process. - tags: list of tags the provider will use. - - pool_association_weights: range in which to draw the weight of association between - the provider and each pool. The provider will use the pool with the largest weight. - provider_config_space: a ConfigurationSpace for the "config" field of the provider. - provider_config_resolver: a function (or callable) taking a Configuration and a prefix and returning the provider's "config" field (dict) from the Configuration. @@ -1500,6 +1472,7 @@ def space(*, type: str, max_num_pools: int, tags: list[str] = [], cs = ConfigurationSpace() cs.add(Constant('type', type)) cs.add(Constant('tags', tags)) + if provider_config_space is not None: cs.add_configuration_space( prefix='config', delimiter='.', @@ -1510,12 +1483,11 @@ def space(*, type: str, max_num_pools: int, tags: list[str] = [], prefix='dependencies', delimiter='.', configuration_space=dependency_config_space) cs.add(Constant('dependency_resolver', dependency_resolver)) - cs.add(Categorical('pool', list(range(max_num_pools)))) return cs @staticmethod - def from_config(*, name: str, provider_id: int, pools: list[PoolSpec], - config: 'Configuration', prefix: str = ''): + def from_config(*, name: str, provider_id: int, + config: Config, prefix: str = '') -> 'ProviderSpec': """ Create a ProviderSpec from a given Configuration object. @@ -1527,7 +1499,6 @@ def from_config(*, name: str, provider_id: int, pools: list[PoolSpec], tags = config[f'{prefix}tags'] provider_config_resolver = config[f'{prefix}config_resolver'] dependency_resolver = config[f'{prefix}dependency_resolver'] - pool = pools[int(config[f'{prefix}pool'])] if provider_config_resolver is None: provider_config = {} else: @@ -1538,79 +1509,10 @@ def from_config(*, name: str, provider_id: int, pools: list[PoolSpec], provider_dependencies = dependency_resolver(config, f'{prefix}dependencies.') return ProviderSpec( name=name, type=type, provider_id=provider_id, - pool=pool, config=provider_config, tags=tags, + config=provider_config, tags=tags, dependencies=provider_dependencies) -@attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) -class ClientSpec: - """Client specification. - - :param name: Name of the client - :type name: str - - :param type: Type of client - :type type: str - - :param config: Configuration - :type config: dict - - :param dependencies: Dependencies - :type dependencies: dict - - :param tags: Tags - :type tags: List[str] - """ - - name: str = attr.ib( - validator=[instance_of(str), _validate_object_name], - on_setattr=attr.setters.frozen) - type: str = attr.ib( - validator=instance_of(str), - on_setattr=attr.setters.frozen) - config: dict = attr.ib( - validator=instance_of(dict), - factory=dict) - dependencies: dict = attr.ib( - validator=instance_of(dict), - factory=dict) - tags: List[str] = attr.ib( - validator=instance_of(List), - factory=list) - - def to_dict(self) -> dict: - """Convert the ClientSpec into a dictionary. - """ - return {'name': self.name, - 'type': self.type, - 'dependencies': self.dependencies, - 'config': self.config, - 'tags': self.tags} - - @staticmethod - def from_dict(data: dict) -> 'ClientSpec': - """Construct a ClientSpec from a dictionary. - - :param data: Dictionary - :type data: dict - """ - return ClientSpec(**data) - - def to_json(self, *args, **kwargs) -> str: - """Convert the ClientSpec into a JSON string. - """ - return json.dumps(self.to_dict(), *args, **kwargs) - - @staticmethod - def from_json(json_string: str) -> 'ClientSpec': - """Construct a ClientSpec from a JSON string. - - :param json_string: JSON string - :type json_string: str - """ - return ClientSpec.from_dict(json.loads(json_string)) - - @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class BedrockSpec: """Bedrock specification. @@ -1698,21 +1600,15 @@ class ProcSpec: :param providers: List of ProviderSpec :type providers: list - - :param clients: List of ClientSpec - :type clients: list """ margo: MargoSpec = attr.ib( validator=instance_of(MargoSpec), converter=_margo_from_args) - libraries: dict = attr.ib( - factory=dict, - validator=instance_of(dict)) - _providers: list = attr.ib( + libraries: list = attr.ib( factory=list, validator=instance_of(list)) - _clients: list = attr.ib( + _providers: list = attr.ib( factory=list, validator=instance_of(list)) bedrock: BedrockSpec = attr.ib( @@ -1727,20 +1623,12 @@ def providers(self) -> SpecListDecorator: """ return SpecListDecorator(list=self._providers, type=ProviderSpec) - @property - def clients(self) -> SpecListDecorator: - """Return a decorator to access the internal list of ClientSpec - and validate changes to this list. - """ - return SpecListDecorator(list=self._clients, type=ClientSpec) - def to_dict(self) -> dict: """Convert the ProcSpec into a dictionary. """ data = {'margo': self.margo.to_dict(), 'libraries': self.libraries, 'providers': [p.to_dict() for p in self._providers], - 'clients': [c.to_dict() for c in self._clients], 'bedrock': self.bedrock.to_dict()} return data @@ -1752,21 +1640,16 @@ def from_dict(data: dict) -> 'ProcSpec': libraries = dict() providers = [] bedrock = {} - clients = [] if 'libraries' in data: libraries = data['libraries'] if 'providers' in data: for p in data['providers']: - providers.append(ProviderSpec.from_dict(p, margo.argobots)) - if 'clients' in data: - for c in data['clients']: - clients.append(ClientSpec.from_dict(c)) + providers.append(ProviderSpec.from_dict(p)) if 'bedrock' in data: bedrock = BedrockSpec.from_dict(data['bedrock'], margo.argobots) return ProcSpec(margo=margo, libraries=libraries, providers=providers, - clients=clients, bedrock=bedrock) def to_json(self, *args, **kwargs) -> str: @@ -1795,14 +1678,10 @@ def validate(self) -> NoReturn: if p.type not in self._libraries: raise ValueError('Could not find module library for' + f'module type {p.name}') - for c in self._clients: - if c.type not in self._libraries: - raise ValueError('Could not find module library for' + - f'module type {p.name}') @staticmethod def space(*, provider_space_factories: list[dict] = [], - **kwargs): + **kwargs) -> CS: """ The provider_space_factories argument is a list of dictionaries with the following format. ``` @@ -1853,15 +1732,6 @@ def space(*, provider_space_factories: list[dict] = [], cs.add_configuration_space( prefix=space_prefix, delimiter='.', configuration_space=provider_cs) - # get the hyperparameter for the pool used by this provider - hp_pool = cs[f'{space_prefix}.pool'] - # add a constraint on it (cannot have pool > num_pools) - # Note: pool is a categorical hyperparameter so we need a - # ForbiddenInClause for each subset of values it can take - for j in range(min_num_pools, max_num_pools): - cs.add(ForbiddenAndConjunction( - ForbiddenEqualsClause(hp_num_pools, j), - ForbiddenInClause(hp_pool, list(range(j, max_num_pools))))) # add conditions on all the hyperparameters of the sub-space, # they exist only if i < num_providers. if i <= hp_num_providers.lower: @@ -1872,7 +1742,7 @@ def space(*, provider_space_factories: list[dict] = [], return cs @staticmethod - def from_config(*, config: 'Configuration', prefix: str = '', **kwargs): + def from_config(*, config: Config, prefix: str = '', **kwargs) -> 'ProcSpec': """ Create a ProcSpec from the provided Configuration object. Extra parameters (**kwargs) will be propagated to the underlying @@ -1889,7 +1759,7 @@ def from_config(*, config: 'Configuration', prefix: str = '', **kwargs): for i in range(num_providers): provider_specs.append( ProviderSpec.from_config( - name=f'{family}_{i}', pools=margo_spec.argobots.pools, + name=f'{family}_{i}', #pools=margo_spec.argobots.pools, provider_id=current_provider_id, config=config, prefix=f'{prefix}providers.{family}[{i}].')) current_provider_id += 1 @@ -1965,7 +1835,7 @@ def check_provider_dependency(dep: str): @staticmethod def space(*, process_space_factories: list[dict] = [], - **kwargs): + **kwargs) -> CS: """ The process_space_factories argument is a list of dictionaries with the following format. ``` @@ -2011,8 +1881,8 @@ def space(*, process_space_factories: list[dict] = [], return cs @staticmethod - def from_config(config: 'Configuration', - prefix: str = '', **kwargs): + def from_config(config: Config, + prefix: str = '', **kwargs) -> 'ServiceSpec': """ Create a ServiceSpec from the provided Configuration object. Extra parameters (**kwargs) will be propagated to the underlying @@ -2040,7 +1910,6 @@ def from_config(config: 'Configuration', attr.resolve_types(ArgobotsSpec, globals(), locals()) attr.resolve_types(MargoSpec, globals(), locals()) attr.resolve_types(ProviderSpec, globals(), locals()) -attr.resolve_types(ClientSpec, globals(), locals()) attr.resolve_types(BedrockSpec, globals(), locals()) attr.resolve_types(ProcSpec, globals(), locals()) attr.resolve_types(ServiceSpec, globals(), locals()) diff --git a/python/mochi/bedrock/test_client_manager.py b/python/mochi/bedrock/test_client_manager.py deleted file mode 100644 index b8587e5..0000000 --- a/python/mochi/bedrock/test_client_manager.py +++ /dev/null @@ -1,89 +0,0 @@ -import unittest -import pymargo.logging -import mochi.bedrock.server as mbs -import mochi.bedrock.spec as spec - - -class TestClientManager(unittest.TestCase): - - def setUp(self): - config = { - "libraries": { - "module_a": "./libModuleA.so", - "module_b": "./libModuleB.so" - }, - "clients": [ - { - "name": "my_client_A", - "type": "module_a" - }, - { - "name": "my_client_B", - "type": "module_b", - "__if__": "false" - } - ] - } - self.server = mbs.Server(address="na+sm", config=config) - self.server.margo.engine.logger.set_log_level(pymargo.logging.level.critical) - - def tearDown(self): - self.server.finalize() - del self.server - - def test_get_client_manager(self): - clients = self.server.clients - self.assertIsInstance(clients, mbs.ClientManager) - self.assertEqual(len(clients), 1) - self.assertIn("my_client_A", clients) - self.assertNotIn("not_my_client_A", clients) - client_A = clients[0] - client_B = clients["my_client_A"] - self.assertEqual(client_A.name, client_B.name) - self.assertEqual(client_A.type, client_B.type) - self.assertEqual(client_A.handle, client_B.handle) - with self.assertRaises(mbs.BedrockException): - c = clients[1] - with self.assertRaises(mbs.BedrockException): - c = clients["bla"] - - def test_client_manager_config(self): - config = self.server.clients.config - self.assertIsInstance(config, list) - self.assertEqual(len(config), 1) - client_1 = config[0] - self.assertIsInstance(client_1, dict) - for key in ["name", "config", "dependencies", "tags", "type"]: - self.assertIn(key, client_1) - - def test_client_manager_spec(self): - spec_list = self.server.clients.spec - self.assertIsInstance(spec_list, list) - for s in spec_list: - self.assertIsInstance(s, spec.ClientSpec) - - def test_add_client(self): - clients = self.server.clients - clients.create( - name="my_client_B", - type="module_b") - self.assertEqual(len(clients), 2) - client_A = clients[1] - client_B = clients["my_client_B"] - self.assertEqual(client_A.name, client_B.name) - self.assertEqual(client_A.type, client_B.type) - self.assertEqual(client_A.handle, client_B.handle) - - def test_remove_client(self): - self.test_add_client() - clients = self.server.clients - del clients["my_client_B"] - self.assertEqual(len(clients), 1) - with self.assertRaises(mbs.BedrockException): - c = clients[1] - with self.assertRaises(mbs.BedrockException): - c = clients["my_provider_B"] - - -if __name__ == '__main__': - unittest.main() diff --git a/python/mochi/bedrock/test_config_space.py b/python/mochi/bedrock/test_config_space.py index 4045593..4be7c0e 100644 --- a/python/mochi/bedrock/test_config_space.py +++ b/python/mochi/bedrock/test_config_space.py @@ -72,7 +72,7 @@ def test_proc_config_space(self): def test_provider_config_space(self): from .config_space import ConfigurationSpace, Integer # pools to select from - pools = [PoolSpec(name=f'pool_{i}') for i in range(5)] + # pools = [PoolSpec(name=f'pool_{i}') for i in range(5)] # config space for the provider config_cs = ConfigurationSpace() @@ -90,7 +90,7 @@ def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: return {'abc': 'def'} space = ProviderSpec.space( - type='yokan', max_num_pools=len(pools), + type='yokan', tags=['tag1', 'tag2'], provider_config_space=config_cs, provider_config_resolver=resolve_provider_config, @@ -102,7 +102,7 @@ def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: spec = ProviderSpec.from_config( name='my_yokan_provider', provider_id=1, - pools=pools, config=config) + config=config) #print(spec.to_json(indent=4)) def test_proc_with_providers(self): @@ -127,7 +127,8 @@ def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: "family": "databases", "space": ProviderSpec.space( type='yokan', - max_num_pools=max_num_pools, tags=['tag1', 'tag2'], + #max_num_pools=max_num_pools, + tags=['tag1', 'tag2'], provider_config_space=provider_config_cs, provider_config_resolver=resolve_provider_config, dependency_resolver=resolve_provider_dependencies), diff --git a/python/mochi/bedrock/test_dependencies.py b/python/mochi/bedrock/test_dependencies.py index 64b0e34..5f2780b 100644 --- a/python/mochi/bedrock/test_dependencies.py +++ b/python/mochi/bedrock/test_dependencies.py @@ -23,11 +23,11 @@ def setUp(self): ] } }, - "libraries": { - "module_a": "./libModuleA.so", - "module_b": "./libModuleB.so", - "module_c": "./libModuleC.so", - }, + "libraries": [ + "./libModuleA.so", + "./libModuleB.so", + "./libModuleC.so", + ], "providers": [ { "name": "my_provider_a", @@ -39,16 +39,6 @@ def setUp(self): "type": "module_b", "provider_id": 2 } - ], - "clients": [ - { - "name": "my_client_a", - "type": "module_a" - }, - { - "name": "my_client_b", - "type": "module_b" - } ] } self.server = mbs.Server(address="na+sm", config=config) @@ -58,7 +48,7 @@ def tearDown(self): self.server.finalize() del self.server - def make_client_params(self, expected_dependencies: dict={}): + def make_provider_params(self, expected_dependencies: dict={}): params = { "name": "my_provider_C", "type": "module_c", @@ -66,87 +56,41 @@ def make_client_params(self, expected_dependencies: dict={}): "expected_client_dependencies": expected_dependencies } } - return params - - def make_provider_params(self, expected_dependencies: dict={}): - params = self.make_client_params({}) params["provider_id"] = 3 - params["pool"] = "my_pool" params["config"]["expected_provider_dependencies"] = expected_dependencies return params - def test_no_dependency(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - client_params = self.make_client_params() - clients.create(**client_params) provider_params = self.make_provider_params() providers.create(**provider_params) self.assertEqual(len(providers), 3) - self.assertEqual(len(clients), 3) def test_optional_dependency(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - client_params = self.make_client_params([ - {"name": "dep1", - "type": "module_a", - "kind": "provider_handle", - "is_array": False, - "is_required": False, - }]) - clients.create(**client_params) provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "kind": "provider_handle", "is_array": False, "is_required": False, }]) providers.create(**provider_params) self.assertEqual(len(providers), 3) - self.assertEqual(len(clients), 3) def test_required_dependency(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", - "type": "module_a", - "kind": "provider_handle", - "is_array": False, - "is_required": True, - }]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = { - "dep1": "my_provider_a@local" - } - clients.create(**client_params) - self.assertEqual(len(clients), 3) # Try creating a provider without the required dependency provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "kind": "provider_handle", "is_array": False, "is_required": True, }]) @@ -163,24 +107,6 @@ def test_required_dependency(self): def test_dependency_on_pool(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "pool", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with a wrong dependency - client_params["dependencies"] = {"dep1": "my_pool_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_pool"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) # Try creating a provider without the required dependency provider_params = self.make_provider_params([ @@ -201,24 +127,6 @@ def test_dependency_on_pool(self): def test_dependency_on_xstream(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "xstream", "is_required": True}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong dependency - client_params["dependencies"] = {"dep1": "my_xstream_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_xstream"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) # Try creating a provider without the required dependency provider_params = self.make_provider_params([ @@ -236,73 +144,14 @@ def test_dependency_on_xstream(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) - def test_dependency_on_client(self): - providers = self.server.providers - self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "client"}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong dependency - client_params["dependencies"] = {"dep1": "my_client_a_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_client_a"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - - # Try creating a provider without the required dependency - provider_params = self.make_provider_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "client"}]) - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the wrong dependency - provider_params["dependencies"] = {"dep1": "my_client_a_bad"} - with self.assertRaises(mbs.BedrockException): - providers.create(**provider_params) - - # Try creating a provider with the required dependency - provider_params["dependencies"] = {"dep1": "my_client_a"} - providers.create(**provider_params) - self.assertEqual(len(providers), 3) - def test_dependency_on_provider(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider"}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong dependency - client_params["dependencies"] = {"dep1": "my_provider_a_bad"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "my_provider_a"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) # Try creating a provider without the required dependency provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider"}]) + "is_required": True}]) with self.assertRaises(mbs.BedrockException): providers.create(**provider_params) @@ -319,31 +168,10 @@ def test_dependency_on_provider(self): def test_dependency_on_provider_with_id(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) - - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider"}]) - - # Try creating a client with dependency on the wrong provider ID - client_params["dependencies"] = {"dep1": "module_a:999"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with dependency on the wrong provider type - client_params["dependencies"] = {"dep1": "module_b:2"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": "module_a:1"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider"}]) + "is_required": True}]) # Try creating a provider with dependency on the wrong provider ID provider_params["dependencies"] = {"dep1": "module_a:999"} @@ -363,38 +191,14 @@ def test_dependency_on_provider_with_id(self): def test_dependency_on_ph_with_id_and_address(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) # Get the address of this process to use instead of "local" address = str(self.server.margo.engine.address) - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong provider ID - client_params["dependencies"] = {"dep1": "module_a:999@{address}"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong module - client_params["dependencies"] = {"dep1": "module_b:1@{address}"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": f"module_a:1@{address}"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - # Try creating a provider without the required dependency provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) + "is_required": True}]) with self.assertRaises(mbs.BedrockException): providers.create(**provider_params) @@ -416,38 +220,14 @@ def test_dependency_on_ph_with_id_and_address(self): def test_dependency_on_ph_with_id_and_rank(self): providers = self.server.providers self.assertEqual(len(providers), 2) - clients = self.server.clients - self.assertEqual(len(clients), 2) # Get the rank of the process to use instead of "local" rank = 0 - # Try creating a client without the required dependency - client_params = self.make_client_params([ - {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong provider ID - client_params["dependencies"] = {"dep1": "module_a:999@{rank}"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the wrong module - client_params["dependencies"] = {"dep1": "module_b:1@{rank}"} - with self.assertRaises(mbs.BedrockException): - clients.create(**client_params) - - # Try creating a client with the required dependency - client_params["dependencies"] = {"dep1": f"module_a:1@{rank}"} - clients.create(**client_params) - self.assertEqual(len(clients), 3) - # Try creating a provider without the required dependency provider_params = self.make_provider_params([ {"name": "dep1", "type": "module_a", - "is_required": True, "kind": "provider_handle"}]) + "is_required": True}]) with self.assertRaises(mbs.BedrockException): providers.create(**provider_params) diff --git a/python/mochi/bedrock/test_provider_manager.py b/python/mochi/bedrock/test_provider_manager.py index dc7960a..e14b975 100644 --- a/python/mochi/bedrock/test_provider_manager.py +++ b/python/mochi/bedrock/test_provider_manager.py @@ -8,10 +8,10 @@ class TestProviderManager(unittest.TestCase): def setUp(self): config = { - "libraries": { - "module_a": "./libModuleA.so", - "module_b": "./libModuleB.so" - }, + "libraries": [ + "./libModuleA.so", + "./libModuleB.so" + ], "providers": [ { "name": "my_provider_A", @@ -44,7 +44,6 @@ def test_get_provider_manager(self): self.assertEqual(provider_A.name, provider_B.name) self.assertEqual(provider_A.type, provider_B.type) self.assertEqual(provider_A.provider_id, provider_B.provider_id) - self.assertEqual(provider_A.handle, provider_B.handle) with self.assertRaises(mbs.BedrockException): p = providers[1] with self.assertRaises(mbs.BedrockException): @@ -56,7 +55,7 @@ def test_provider_manager_config(self): self.assertEqual(len(config), 1) provider_1 = config[0] self.assertIsInstance(provider_1, dict) - for key in ["name", "pool", "config", "provider_id", "dependencies", "tags", "type"]: + for key in ["name", "config", "provider_id", "dependencies", "tags", "type"]: self.assertIn(key, provider_1) def test_provider_manager_spec(self): @@ -69,7 +68,6 @@ def test_add_provider(self): providers = self.server.providers providers.create( name="my_provider_B", - pool="__primary__", provider_id=2, type="module_b") self.assertEqual(len(providers), 2) @@ -78,7 +76,6 @@ def test_add_provider(self): self.assertEqual(provider_A.name, provider_B.name) self.assertEqual(provider_A.type, provider_B.type) self.assertEqual(provider_A.provider_id, provider_B.provider_id) - self.assertEqual(provider_A.handle, provider_B.handle) def test_remove_provider(self): self.test_add_provider() diff --git a/python/mochi/bedrock/test_server.py b/python/mochi/bedrock/test_server.py index 90d4f44..0f8fa52 100644 --- a/python/mochi/bedrock/test_server.py +++ b/python/mochi/bedrock/test_server.py @@ -36,7 +36,7 @@ def test_server_config(self): server = mbs.Server(address="na+sm") config = server.config self.assertIsInstance(config, dict) - for expected_key in ["margo", "bedrock", "providers", "clients", "libraries"]: + for expected_key in ["margo", "bedrock", "providers", "libraries"]: self.assertIn(expected_key, config) server.finalize() diff --git a/python/mochi/bedrock/test_service_group_handle.py b/python/mochi/bedrock/test_service_group_handle.py index a7992da..517269b 100644 --- a/python/mochi/bedrock/test_service_group_handle.py +++ b/python/mochi/bedrock/test_service_group_handle.py @@ -12,20 +12,20 @@ def setUp(self): self.tempdir = tempfile.TemporaryDirectory() self.groupfile = os.path.join(self.tempdir.name, "group.flock") config = { - "libraries": { - "flock": "libflock-bedrock-module.so" - }, + "libraries": [ + "libflock-bedrock-module.so" + ], "providers": [{ "name": "my_group", "type": "flock", "provider_id" : 1, "config": { - "bootstrap": "self", - "file": self.groupfile, - "group": { - "type": "static" - } - } + "bootstrap": "self", + "file": self.groupfile, + "group": { + "type": "static" + } + }, }] } self.server = mbs.Server(address="na+sm", config=config) @@ -53,20 +53,23 @@ def setUp(self): self.tempdir = tempfile.TemporaryDirectory() self.groupfile = os.path.join(self.tempdir.name, "group.flock") config = { - "libraries": { - "flock": "libflock-bedrock-module.so" - }, + "libraries": [ + "libflock-bedrock-module.so" + ], "providers": [{ "name": "my_group", "type": "flock", "provider_id" : 1, "config": { - "bootstrap": "self", - "file": self.groupfile, - "group": { - "type": "static" - } - } + "bootstrap": "self", + "file": self.groupfile, + "group": { + "type": "static" + } + }, + "dependencies": { + "pool": "__primary__" + } }] } self.server = mbs.Server(address="na+sm", config=config) diff --git a/python/mochi/bedrock/test_service_handle.py b/python/mochi/bedrock/test_service_handle.py index 227926a..e5a3ba4 100644 --- a/python/mochi/bedrock/test_service_handle.py +++ b/python/mochi/bedrock/test_service_handle.py @@ -52,7 +52,7 @@ def test_client(self): def test_config(self): config = self.sh.config self.assertIsInstance(config, dict) - for k in ["margo", "providers", "clients", "bedrock"]: + for k in ["margo", "providers", "bedrock"]: self.assertIn(k, config) def test_spec(self): @@ -67,10 +67,10 @@ def test_query(self): s = spec.ArgobotsSpec.from_dict(result) def test_load_module(self): - self.sh.load_module("module_a", "./libModuleA.so") - self.sh.load_module("module_b", "./libModuleB.so") + self.sh.load_module("./libModuleA.so") + self.sh.load_module("./libModuleB.so") with self.assertRaises(mbc.ClientException): - self.sh.load_module("module_x", "./libModuleX.so") + self.sh.load_module("./libModuleX.so") def add_pool(self, config): initial_num_pools = len(self.server.margo.pools) @@ -180,51 +180,11 @@ def test_remove_xstream(self): with self.assertRaises(mbc.ClientException): self.server.margo.xstreams["my_xstream"] - def test_add_client_from_dict(self): - self.test_load_module() - client_config = { - "name": "my_client", - "type": "module_a", - "config": {}, - "dependencies": {}, - "tags": ["my_tag_1", "my_tag_2"] - } - self.sh.add_client(client_config) - proc_spec = self.server.spec - client_spec = proc_spec.clients["my_client"] - - def test_add_client_from_src(self): - self.test_load_module() - client_config = { - "name": "my_client", - "type": "module_a", - "config": {}, - "dependencies": {}, - "tags": ["my_tag_1", "my_tag_2"] - } - self.sh.add_client(json.dumps(client_config)) - proc_spec = self.server.spec - client_spec = proc_spec.clients["my_client"] - - def test_add_client_from_spec(self): - self.test_load_module() - client_config = spec.ClientSpec( - name="my_client", - type="module_a", - config={}, - dependencies={}, - tags=["my_tag_1", "my_tag_2"] - ) - self.sh.add_client(client_config) - proc_spec = self.server.spec - client_spec = proc_spec.clients["my_client"] - def test_add_provider_from_dict(self): self.test_load_module() provider_config = { "name": "my_provider", "type": "module_a", - "pool": "__primary__", "provider_id": 42, "config": {}, "dependencies": {}, @@ -239,7 +199,6 @@ def test_add_provider_from_str(self): provider_config = { "name": "my_provider", "type": "module_a", - "pool": "__primary__", "provider_id": 42, "config": {}, "dependencies": {}, @@ -254,7 +213,6 @@ def test_add_provider_from_spec(self): provider_config = spec.ProviderSpec( name="my_provider", type="module_a", - pool=spec.PoolSpec(name="__primary__"), provider_id=42, config={}, dependencies={}, diff --git a/python/src/py-bedrock-client.cpp b/python/src/py-bedrock-client.cpp index 1b0c583..99ab738 100644 --- a/python/src/py-bedrock-client.cpp +++ b/python/src/py-bedrock-client.cpp @@ -75,10 +75,9 @@ PYBIND11_MODULE(pybedrock_client, m) { }, "script"_a) .def("load_module", [](const ServiceHandle& sh, - const std::string& name, const std::string& path) { - sh.loadModule(name, path); - }, "name"_a, "path"_a) + sh.loadModule(path); + }, "path"_a) .def("add_provider", [](const ServiceHandle& sh, const std::string& description) { @@ -86,17 +85,6 @@ PYBIND11_MODULE(pybedrock_client, m) { sh.addProvider(description, &provider_id_out); return provider_id_out; }, "description"_a) - .def("change_provider_pool", - [](const ServiceHandle& sh, - const std::string& provider_name, - const std::string& pool_name) { - sh.changeProviderPool(provider_name, pool_name); - }) - .def("add_client", - [](const ServiceHandle& sh, - const std::string& description) { - sh.addClient(description); - }, "description"_a) .def("add_pool", [](const ServiceHandle& sh, const std::string& config) { sh.addPool(config); }, diff --git a/python/src/py-bedrock-server.cpp b/python/src/py-bedrock-server.cpp index 27525bd..e76cf77 100644 --- a/python/src/py-bedrock-server.cpp +++ b/python/src/py-bedrock-server.cpp @@ -35,8 +35,6 @@ PYBIND11_MODULE(pybedrock_server, m) { [](std::shared_ptr nd) { return nd->getName(); }) .def_property_readonly("type", [](std::shared_ptr nd) { return nd->getType(); }) - .def_property_readonly("handle", - [](std::shared_ptr nd) { return nd->getHandle(); }) ; py11::class_> (m, "ProviderDependency", named_dep) @@ -82,10 +80,6 @@ PYBIND11_MODULE(pybedrock_server, m) { [](std::shared_ptr server) { return server->getProviderManager(); }) - .def_property_readonly("client_manager", - [](std::shared_ptr server) { - return server->getClientManager(); - }) ; py11::class_ (m, "MargoManager") @@ -143,9 +137,6 @@ PYBIND11_MODULE(pybedrock_server, m) { .def("add_provider", &ProviderManager::addProviderFromJSON, "description"_a) - .def("change_pool", - &ProviderManager::changeProviderPool, - "provider"_a, "pool"_a) .def("migrate_provider", &ProviderManager::migrateProvider, "provider"_a, "dest_addr"_a, "dest_provider_id"_a, @@ -157,29 +148,4 @@ PYBIND11_MODULE(pybedrock_server, m) { &ProviderManager::restoreProvider, "provider"_a, "src_path"_a, "restore_config"_a) ; - - py11::class_ (m, "ClientManager") - .def_property_readonly("config", &ClientManager::getCurrentConfig) - .def("get_client", [](const ClientManager& cm, const std::string& name) { - return cm.getClient(name); - }, - "name"_a) - .def("get_client", [](const ClientManager& cm, size_t index) { - return cm.getClient(index); - }, - "index"_a) - .def_property_readonly("num_clients", &ClientManager::numClients) - .def("remove_client", [](ClientManager& cm, const std::string& name) { - return cm.removeClient(name); - }, - "name"_a) - .def("remove_client", [](ClientManager& cm, size_t index) { - return cm.removeClient(index); - }, - "index"_a) - .def("get_client_or_create", &ClientManager::getOrCreateAnonymous, - "type"_a) - .def("add_client", &ClientManager::addClientFromJSON, - "description"_a) - ; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4df42a8..af926d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,6 @@ set (server-src-files Server.cpp MargoManager.cpp ProviderManager.cpp - ClientManager.cpp DependencyFinder.cpp MargoLogging.cpp Jx9Manager.cpp diff --git a/src/ClientManager.cpp b/src/ClientManager.cpp deleted file mode 100644 index 4792222..0000000 --- a/src/ClientManager.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#include -#include -#include -#include -#include - -#include "ClientManagerImpl.hpp" -#include "JsonUtil.hpp" - -#include -#include -#include -#include -#include - -namespace tl = thallium; - -namespace bedrock { - -using namespace std::string_literals; -using nlohmann::json; - -ClientManager::ClientManager(const MargoManager& margo, - const Jx9Manager& jx9, - uint16_t provider_id, - const std::shared_ptr& pool) -: self(std::make_shared(margo.getThalliumEngine(), - provider_id, tl::pool(pool->getHandle()))) { - self->m_margo_manager = margo; - self->m_jx9_manager = jx9; -} - -// LCOV_EXCL_START - -ClientManager::ClientManager(const ClientManager&) = default; - -ClientManager::ClientManager(ClientManager&&) = default; - -ClientManager& ClientManager::operator=(const ClientManager&) = default; - -ClientManager& ClientManager::operator=(ClientManager&&) = default; - -ClientManager::~ClientManager() = default; - -ClientManager::operator bool() const { return static_cast(self); } - -// LCOV_EXCL_STOP - -void ClientManager::setDependencyFinder(const DependencyFinder& finder) { - self->m_dependency_finder = finder; -} - -size_t ClientManager::numClients() const { - std::lock_guard lock(self->m_clients_mtx); - return self->m_clients.size(); -} - -std::shared_ptr ClientManager::getClient(const std::string& name) const { - std::lock_guard lock(self->m_clients_mtx); - auto it = self->findByName(name); - if (it == self->m_clients.end()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find client \"{}\"", name); - return *it; -} - -std::shared_ptr ClientManager::getClient(size_t index) const { - std::lock_guard lock(self->m_clients_mtx); - if (index >= self->m_clients.size()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find client at index {}", index); - return self->m_clients[index]; -} - -std::shared_ptr ClientManager::getOrCreateAnonymous(const std::string& type) { - { - std::lock_guard lock(self->m_clients_mtx); - for (const auto& client : self->m_clients) { - if (client->getType() == type) { - return client; - } - } - // no client of this type found, try creating one with name - // __type_client__ first we need to check whether we have the module for - // such a client - auto service_factory = ModuleContext::getServiceFactory(type); - if (!service_factory) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find service factory for client type \"{}\"", type); - } - // find out if such a client has required dependencies - for (const auto& dependency : - service_factory->getClientDependencies("{}")) { - if (dependency.flags & BEDROCK_REQUIRED) - throw BEDROCK_DETAILED_EXCEPTION( - "Could not create default client of type \"{}\" because" - " it requires dependency \"{}\"", - type, dependency.name); - } - } - - // we can create the client - std::string name = "__"s + type + "_client__"; - ResolvedDependencyMap dependencies; - - addClient(name, type, json::object(), dependencies); - // get the client - auto it = self->findByName(name); - return *it; -} - -std::shared_ptr -ClientManager::addClient(const std::string& name, - const std::string& type, - const json& config, - const ResolvedDependencyMap& dependencies, - const std::vector& tags) { - std::shared_ptr entry; - auto service_factory = ModuleContext::getServiceFactory(type); - if (!service_factory) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find service factory for client type \"{}\"", type); - } - - { - std::lock_guard lock(self->m_clients_mtx); - auto it = self->findByName(name); - if (it != self->m_clients.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Name \"{}\" is already used by another client", name); - } - - auto margoCtx = MargoManager(self->m_margo_manager); - - FactoryArgs args; - args.name = name; - args.mid = margoCtx.getMargoInstance(); - args.engine = margoCtx.getThalliumEngine(); - args.pool = ABT_POOL_NULL; - args.config = config.dump(); - args.provider_id = std::numeric_limits::max(); - args.tags = tags; - args.dependencies = dependencies; - - auto handle = service_factory->initClient(args); - - entry = std::make_shared( - name, type, - handle, service_factory, dependencies, tags); - - spdlog::trace("Registered client {} of type {}", name, type); - - self->m_clients.push_back(entry); - } - self->m_clients_cv.notify_all(); - return entry; -} - -void ClientManager::removeClient(const std::string& name) { - std::lock_guard lock(self->m_clients_mtx); - auto it = self->findByName(name); - if (it == self->m_clients.end()) { - throw BEDROCK_DETAILED_EXCEPTION("Could not find client with name \"{}\"", name); - } - if(it->use_count() > 1) { - throw BEDROCK_DETAILED_EXCEPTION( - "Cannot destroy client \"{}\" as it is used as dependency", - (*it)->getName()); - } - self->m_clients.erase(it); -} - -void ClientManager::removeClient(size_t index) { - std::lock_guard lock(self->m_clients_mtx); - if (index >= self->m_clients.size()) - throw BEDROCK_DETAILED_EXCEPTION("Could not find client at index {}", index); - if(self->m_clients[index].use_count() > 1) { - throw BEDROCK_DETAILED_EXCEPTION( - "Cannot destroy client at index {} as it is used as dependency", - index); - } - self->m_clients.erase(self->m_clients.begin() + index); -} - -std::shared_ptr -ClientManager::addClientFromJSON(const json& description) { - auto dependencyFinder = DependencyFinder(self->m_dependency_finder); - static const json configSchema = R"( - { - "$schema": "https://json-schema.org/draft/2019-09/schema", - "type": "object", - "properties": { - "name": {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - "type": {"type": "string"}, - "tags": { - "type": "array", - "items": {"type": "string"} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - {"type": "string"}, - {"type": "array", "items": {"type": "string"}} - ] - } - }, - "config": {"type": "object"} - }, - "required": ["name", "type"] - } - )"_json; - static const JsonValidator validator{configSchema}; - validator.validate(description, "ClientManager"); - - auto& name = description["name"].get_ref(); - auto& type = description["type"].get_ref(); - - auto service_factory = ModuleContext::getServiceFactory(type); - if (!service_factory) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find service factory for client type \"{}\"", type); - } - - auto config = description.value("config", json::object()); - auto configStr = config.is_null() ? std::string{"{}"} : config.dump(); - std::vector tags; - for(auto& tag : description.value("tags", json::array())) { - tags.push_back(tag.get()); - } - - auto deps_from_config = description.value("dependencies", json::object()); - ResolvedDependencyMap resolved_dependency_map; - - for (const auto& dependency : service_factory->getClientDependencies(configStr.c_str())) { - spdlog::trace("Resolving dependency {}", dependency.name); - if (deps_from_config.contains(dependency.name)) { - auto dep_config = deps_from_config[dependency.name]; - if (!(dependency.flags & BEDROCK_ARRAY)) { - if (dep_config.is_array() && dep_config.size() == 1) { - // an array of length 1 can be converted into a single string - dep_config = dep_config[0]; - } - if (!dep_config.is_string()) { - throw BEDROCK_DETAILED_EXCEPTION("Dependency \"{}\" should be a string", - dependency.name); - } - auto ptr = dependencyFinder.find( - dependency.type, BEDROCK_GET_KIND_FROM_FLAG(dependency.flags), - dep_config.get(), nullptr); - resolved_dependency_map[dependency.name].dependencies.push_back(ptr); - resolved_dependency_map[dependency.name].is_array = false; - } else { - if (dep_config.is_string()) { - // a single string can be converted into an array of size 1 - auto tmp_array = json::array(); - tmp_array.push_back(dep_config); - dep_config = tmp_array; - } - if (!dep_config.is_array()) { - throw BEDROCK_DETAILED_EXCEPTION("Dependency \"{}\" should be an array", - dependency.name); - } - std::vector deps; - for (const auto& elem : dep_config) { - auto ptr = dependencyFinder.find( - dependency.type, BEDROCK_GET_KIND_FROM_FLAG(dependency.flags), - elem.get(), nullptr); - resolved_dependency_map[dependency.name].dependencies.push_back(ptr); - resolved_dependency_map[dependency.name].is_array = true; - } - } - } else if (dependency.flags & BEDROCK_REQUIRED) { - throw BEDROCK_DETAILED_EXCEPTION( - "Missing dependency \"{}\" of type \"{}\" in provider configuration", - dependency.name, dependency.type); - } - } - - return addClient(name, type, config, resolved_dependency_map, tags); -} - -void ClientManager::addClientListFromJSON(const json& list) { - if (list.is_null()) { return; } - if (!list.is_array()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Invalid JSON configuration passed to " - "ClientManager::addClientListFromJSON (expected array)"); - } - for (const auto& description : list) { - addClientFromJSON(description); - } -} - -json ClientManager::getCurrentConfig() const { - return self->makeConfig(); -} - -} // namespace bedrock diff --git a/src/ClientManagerImpl.hpp b/src/ClientManagerImpl.hpp deleted file mode 100644 index 855028f..0000000 --- a/src/ClientManagerImpl.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * (C) 2020 The University of Chicago - * - * See COPYRIGHT in top-level directory. - */ -#ifndef __BEDROCK_CLIENT_MANAGER_IMPL_H -#define __BEDROCK_CLIENT_MANAGER_IMPL_H - -#include "MargoManagerImpl.hpp" -#include "bedrock/Jx9Manager.hpp" -#include "bedrock/RequestResult.hpp" -#include "bedrock/AbstractServiceFactory.hpp" -#include "bedrock/ClientDescriptor.hpp" -#include "bedrock/ClientManager.hpp" -#include "DependencyFinderImpl.hpp" - -#include -#include -#include - -#include - -namespace bedrock { - -using nlohmann::json; -using namespace std::string_literals; -namespace tl = thallium; - -class ClientEntry : public NamedDependency { - - public: - - AbstractServiceFactory* factory; - ResolvedDependencyMap dependencies; - std::vector tags; - - ClientEntry(std::string name, std::string type, - void* handle, AbstractServiceFactory* f, - ResolvedDependencyMap deps, - std::vector _tags) - : NamedDependency( - std::move(name), - std::move(type), - handle, - [f](void* args) { - if(f) f->finalizeClient(args); - }) - , factory(f) - , dependencies(deps) - , tags(std::move(_tags)) {} - - json makeConfig() const { - auto c = json::object(); - c["name"] = getName(); - c["type"] = getType(); - c["config"] = json::parse(factory->getClientConfig(getHandle())); - c["tags"] = json::array(); - for(auto& t : tags) c["tags"].push_back(t); - c["dependencies"] = json::object(); - auto& d = c["dependencies"]; - for (auto& p : dependencies) { - auto& dep_name = p.first; - auto& dep_group = p.second; - if (dep_group.dependencies.size() == 0) continue; - if (!dep_group.is_array) { - d[dep_name] = dep_group.dependencies[0]->getName(); - } else { - d[dep_name] = json::array(); - for (auto& x : dep_group.dependencies) { - d[dep_name].push_back(x->getName()); - } - } - } - return c; - } -}; - -class ClientManagerImpl -: public tl::provider, - public std::enable_shared_from_this { - - public: - std::shared_ptr m_dependency_finder; - std::vector> m_clients; - mutable tl::mutex m_clients_mtx; - mutable tl::condition_variable m_clients_cv; - - std::shared_ptr m_margo_manager; - std::shared_ptr m_jx9_manager; - - tl::remote_procedure m_lookup_client; - tl::remote_procedure m_add_client; - - ClientManagerImpl(const tl::engine& engine, uint16_t provider_id, - const tl::pool& pool) - : tl::provider(engine, provider_id) - , m_lookup_client(define("bedrock_lookup_client", - &ClientManagerImpl::lookupClientRPC, pool)) - , m_add_client(define("bedrock_add_client", - &ClientManagerImpl::addClientRPC, pool)) - {} - - auto findByName(const std::string& spec) { - auto it = std::find_if( - m_clients.begin(), m_clients.end(), - [&spec](const std::shared_ptr& item) { return item->getName() == spec; }); - return it; - } - - json makeConfig() const { - auto config = json::array(); - std::lock_guard lock(m_clients_mtx); - for (auto& p : m_clients) { config.push_back(p->makeConfig()); } - return config; - } - - private: - void lookupClientRPC(const tl::request& req, const std::string& name, - double timeout) { - double t1 = tl::timer::wtime(); - RequestResult result; - std::unique_lock lock(m_clients_mtx); - auto it = findByName(name); - if (it == m_clients.end() && timeout > 0) { - m_clients_cv.wait(lock, [this, &name, &it, t1, timeout]() { - // FIXME will not actually wake up after timeout - double t2 = tl::timer::wtime(); - it = findByName(name); - return (t2 - t1 > timeout) || (it != m_clients.end()); - }); - } - if (it != m_clients.end()) { - result.value().name = (*it)->getName(); - result.value().type = (*it)->getType(); - } else { - result.error() - = "Could not find client with name \""s + name + "\""; - } - req.respond(result); - } - - void addClientRPC(const tl::request& req, const std::string& description) { - RequestResult result; - json jsonconfig; - try { - if (!description.empty()) - jsonconfig = json::parse(description); - else - jsonconfig = json::object(); - } catch (const std::exception& ex) { - result.error() = "Invalid JSON configuration for client"; - result.success() = false; - req.respond(result); - return; - } - try { - ClientManager(shared_from_this()).addClientFromJSON(jsonconfig); - } catch (const Exception& ex) { - result.error() = ex.what(); - result.success() = false; - } - req.respond(result); - } -}; - -} // namespace bedrock - -#endif diff --git a/src/DependencyFinder.cpp b/src/DependencyFinder.cpp index 229eaba..93942e2 100644 --- a/src/DependencyFinder.cpp +++ b/src/DependencyFinder.cpp @@ -5,9 +5,10 @@ */ #include "DependencyFinderImpl.hpp" #include "bedrock/DependencyFinder.hpp" -#include "bedrock/ModuleContext.hpp" -#include "bedrock/AbstractServiceFactory.hpp" +#include "bedrock/ModuleManager.hpp" +#include "bedrock/AbstractComponent.hpp" #include "bedrock/Exception.hpp" +#include "bedrock/ProviderHandle.hpp" #include #include #include @@ -18,13 +19,11 @@ namespace bedrock { DependencyFinder::DependencyFinder(const MPIEnv& mpi, const MargoManager& margo, - const ProviderManager& pmanager, - const ClientManager& cmanager) + const ProviderManager& pmanager) : self(std::make_shared(margo.getMargoInstance())) { self->m_mpi = mpi.self; self->m_margo_context = margo; self->m_provider_manager = pmanager.self; - self->m_client_manager = cmanager.self; } // LCOV_EXCL_START @@ -45,8 +44,9 @@ DependencyFinder::operator bool() const { return static_cast(self); } // LCOV_EXCL_STOP std::shared_ptr DependencyFinder::find( - const std::string& type, int32_t kind, - const std::string& spec, std::string* resolved) const { + const std::string& type, + const std::string& spec, + std::string* resolved) const { spdlog::trace("DependencyFinder search for {} of type {}", spec, type); if (type == "pool") { // Argobots pool @@ -67,13 +67,7 @@ std::shared_ptr DependencyFinder::find( if (resolved) { *resolved = spec; } return xstream; - } else if (kind == BEDROCK_KIND_CLIENT) { - - auto client = findClient(type, spec); - if (client && resolved) { *resolved = client->getName(); } - return client; - - } else if (kind == BEDROCK_KIND_PROVIDER) { + } else if (spec.find("@") == std::string::npos) { // local provider // the spec can be in the form "name" or "type:id" std::regex re( @@ -101,7 +95,6 @@ std::shared_ptr DependencyFinder::find( } else { // Provider handle std::regex re( - "(?:([a-zA-Z_][a-zA-Z0-9_]*)\\->)?" // client name (name->) "([a-zA-Z_][a-zA-Z0-9_]*)" // identifier (name or type) "(?::([0-9]+))?" // optional provider id "(?:@(.+))?"); // optional locator (@address) @@ -110,27 +103,24 @@ std::shared_ptr DependencyFinder::find( throw Exception("Ill-formated dependency specification \"{}\"", spec); } - auto client_name = match.str(1); // client to use for provider handles - auto identifier = match.str(2); // name or type - auto provider_id_str = match.str(3); // provider id - auto locator = match.str(4); // address or "local" or MPI rank + auto identifier = match.str(1); // name or type + auto provider_id_str = match.str(2); // provider id + auto locator = match.str(3); // address or "local" or MPI rank if(locator.empty()) locator = "local"; if (provider_id_str.empty()) { - // dependency specified as client->name@location - return makeProviderHandle( - client_name, type, identifier, locator, resolved); + // dependency specified as name@location + return makeProviderHandle(type, identifier, locator, resolved); } else { - // dependency specified as client->type:id@location + // dependency specified as type:id@location uint16_t provider_id = atoi(provider_id_str.c_str()); if (type != identifier) { throw Exception( "Invalid provider type in \"{}\" (expected {})", spec, type); } - return makeProviderHandle( - client_name, type, provider_id, locator, resolved); + return makeProviderHandle(type, provider_id, locator, resolved); } } return nullptr; @@ -173,43 +163,16 @@ DependencyFinder::findProvider(const std::string& type, } std::shared_ptr -DependencyFinder::findClient( - const std::string& type, - const std::string& name) const { - auto client_manager_impl = self->m_client_manager.lock(); - if (!client_manager_impl) { - throw Exception("Could not resolve client dependency: no ClientManager found"); - } - if (!name.empty()) { - auto client = ClientManager(client_manager_impl).getClient(name); - if (!client) { - throw Exception("Could not find client named \"{}\"", name); - } else if (type != client->getType()) { - throw Exception( - "Invalid type {} for dependency \"{}\" (expected {})", - client->getType(), name, type); - } - return client; - } else { - auto client = ClientManager(client_manager_impl) - .getOrCreateAnonymous(type); - return client; - } -} - -std::shared_ptr -DependencyFinder::makeProviderHandle(const std::string& client_name, - const std::string& type, +DependencyFinder::makeProviderHandle(const std::string& type, uint16_t provider_id, const std::string& locatorArg, std::string* resolved) const { auto locator = locatorArg; spdlog::trace("Making provider handle of type {} with id {} and locator {}", type, provider_id, locator); - auto mid = MargoManager(self->m_margo_context).getMargoInstance(); - auto client = findClient(type, client_name); - auto service_factory = ModuleContext::getServiceFactory(type); - hg_addr_t addr = HG_ADDR_NULL; + auto engine = MargoManager(self->m_margo_context).getThalliumEngine(); + thallium::endpoint endpoint; + bool locator_is_number = true; int rank = 0; for(auto c : locator) { @@ -241,70 +204,52 @@ DependencyFinder::makeProviderHandle(const std::string& client_name, "Invalid type {} for provider handle to provider of type {}", type, provider->getType()); } - hg_return_t hret = margo_addr_self(mid, &addr); - if (hret != HG_SUCCESS) { + try { + endpoint = engine.self(); + } catch(const std::exception& ex) { throw Exception( - "Failed to get self address (margo_addr_self returned {})", - std::to_string(hret)); + "Failed to get self address (engine.self() exception: {})", + ex.what()); } } else { - hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); - if (hret != HG_SUCCESS) { + try { + endpoint = engine.lookup(locator); + } catch(const std::exception& ex) { throw Exception( "Failed to lookup address {} " - "(margo_addr_lookup returned {})", - locator, std::to_string(hret)); + "(engine.lookup() exception: {})", + locator, ex.what()); } ProviderDescriptor descriptor; - try { - auto spec = type + ":" + std::to_string(provider_id); - auto provider_manager_impl = self->m_provider_manager.lock(); - if (!provider_manager_impl) { - throw Exception("Could not lookup provider: no ProviderManager found"); - } - auto pid = provider_manager_impl->get_provider_id(); - self->lookupRemoteProvider(addr, pid, spec, &descriptor); - } catch (...) { - margo_addr_free(mid, addr); - throw; + auto spec = type + ":" + std::to_string(provider_id); + auto provider_manager_impl = self->m_provider_manager.lock(); + if (!provider_manager_impl) { + throw Exception("Could not lookup provider: no ProviderManager found"); } + auto pid = provider_manager_impl->get_provider_id(); + self->lookupRemoteProvider(endpoint, pid, spec, &descriptor); } - std::string name; - char addr_str[256]; - hg_size_t addr_str_size = 256; - margo_addr_to_string(mid, addr_str, &addr_str_size, addr); - name = client->getName() + "->" + type + ":" - + std::to_string(provider_id) + "@" + addr_str; + auto name = type + ":" + std::to_string(provider_id) + "@" + static_cast(endpoint); if (resolved) *resolved = name; - void* ph = service_factory->createProviderHandle( - client->getHandle(), addr, provider_id); + auto ph = ProviderHandle{endpoint, provider_id}; - margo_addr_free(mid, addr); - return std::make_shared( - std::to_string(provider_id) + "@" + addr_str, - client->getType(), ph, - [service_factory](void* ph) { - service_factory->destroyProviderHandle(ph); - }); + return std::make_shared(name, type, ph); } std::shared_ptr -DependencyFinder::makeProviderHandle(const std::string& client_name, - const std::string& type, +DependencyFinder::makeProviderHandle(const std::string& type, const std::string& name, const std::string& locatorArg, std::string* resolved) const { auto locator = locatorArg; - auto mid = self->m_margo_context->m_mid; - auto client = findClient(type, client_name); - auto service_factory = ModuleContext::getServiceFactory(type); - hg_addr_t addr = HG_ADDR_NULL; + auto engine = MargoManager(self->m_margo_context).getThalliumEngine(); + thallium::endpoint endpoint; ProviderDescriptor descriptor; uint16_t provider_id; spdlog::trace("Making provider handle to provider {} of type {} at {}", @@ -337,62 +282,47 @@ DependencyFinder::makeProviderHandle(const std::string& client_name, "Invalid type {} for provider handle to provider of type {}", type, provider->getType()); } - hg_return_t hret = margo_addr_self(mid, &addr); - if (hret != HG_SUCCESS) { - throw Exception( - "Failed to get self address (margo_addr_self returned {})", - std::to_string(hret)); - } - descriptor = ProviderDescriptor{ - provider->getName(), - provider->getType(), - provider->getProviderID(), - }; - provider_id = provider->getProviderID(); + try { + endpoint = engine.self(); + } catch(const std::exception& ex) { + throw Exception( + "Failed to get self address (engine.self() exception: {})", + ex.what()); + } + descriptor = ProviderDescriptor{ + provider->getName(), + provider->getType(), + provider->getProviderID() + }; + provider_id = provider->getProviderID(); } else { - hg_return_t hret = margo_addr_lookup(mid, locator.c_str(), &addr); - if (hret != HG_SUCCESS) { + try { + endpoint = engine.lookup(locator); + } catch(const std::exception& ex) { throw Exception( "Failed to lookup address {} " - "(margo_addr_lookup returned {})", - locator, std::to_string(hret)); + "(engine.lookup() exception: {})", + locator, ex.what()); } - try { - auto provider_manager_impl = self->m_provider_manager.lock(); - if (!provider_manager_impl) { - throw Exception("Could not get provider id: no ProviderManager found"); - } - auto pid = provider_manager_impl->get_provider_id(); - self->lookupRemoteProvider(addr, pid, name, &descriptor); - } catch (...) { - margo_addr_free(mid, addr); - throw; + auto provider_manager_impl = self->m_provider_manager.lock(); + if (!provider_manager_impl) { + throw Exception("Could not get provider id: no ProviderManager found"); } + auto pid = provider_manager_impl->get_provider_id(); + self->lookupRemoteProvider(endpoint, pid, name, &descriptor); provider_id = descriptor.provider_id; } - std::string ph_name; - char addr_str[256]; - hg_size_t addr_str_size = 256; - margo_addr_to_string(mid, addr_str, &addr_str_size, addr); - ph_name = client->getName() + "->" + type + ":" - + std::to_string(provider_id) + "@" + addr_str; + auto ph_name = type + ":" + std::to_string(provider_id) + "@" + static_cast(endpoint); if (resolved) *resolved = ph_name; - void* ph = service_factory->createProviderHandle( - client->getHandle(), addr, descriptor.provider_id); + auto ph = ProviderHandle{endpoint, provider_id}; - margo_addr_free(mid, addr); - return std::make_shared( - std::to_string(provider_id) + "@" + addr_str, - client->getType(), ph, - [service_factory](void* ph) { - service_factory->destroyProviderHandle(ph); - }); + return std::make_shared(ph_name, type, ph); } } // namespace bedrock diff --git a/src/DependencyFinderImpl.hpp b/src/DependencyFinderImpl.hpp index fc2a64a..3b99a8a 100644 --- a/src/DependencyFinderImpl.hpp +++ b/src/DependencyFinderImpl.hpp @@ -8,7 +8,6 @@ #include "MargoManagerImpl.hpp" #include "ProviderManagerImpl.hpp" -#include "ClientManagerImpl.hpp" #include "Formatting.hpp" #include "MPIEnvImpl.hpp" #include "bedrock/VoidPtr.hpp" @@ -31,7 +30,6 @@ class DependencyFinderImpl { std::shared_ptr m_mpi; std::shared_ptr m_margo_context; std::weak_ptr m_provider_manager; - std::weak_ptr m_client_manager; double m_timeout = 30.0; tl::remote_procedure m_lookup_provider; @@ -46,11 +44,10 @@ class DependencyFinderImpl { spdlog::trace("DependencyFinderImpl destroyed"); } - void lookupRemoteProvider(hg_addr_t addr, uint16_t provider_id, + void lookupRemoteProvider(const tl::endpoint& addr, uint16_t provider_id, const std::string& spec, ProviderDescriptor* desc) { - auto ph = tl::provider_handle(tl::endpoint(m_engine, addr, false), - provider_id); + auto ph = tl::provider_handle(addr, provider_id); RequestResult result = m_lookup_provider.on(ph)(spec, m_timeout); if (result.error() != "") throw Exception(result.error()); diff --git a/src/MargoManager.cpp b/src/MargoManager.cpp index 1f399a0..7b9eebc 100644 --- a/src/MargoManager.cpp +++ b/src/MargoManager.cpp @@ -15,7 +15,6 @@ namespace bedrock { MargoManager::MargoManager(margo_instance_id mid) : self(std::make_shared()) { - self->m_mid = mid; self->m_engine = tl::engine(mid); } @@ -26,32 +25,9 @@ MargoManager::MargoManager(const std::string& address, if (!configString.empty() && configString != "null") { args.json_config = configString.c_str(); } - self->m_mid = margo_init_ext(address.c_str(), MARGO_SERVER_MODE, &args); - if (self->m_mid == MARGO_INSTANCE_NULL) - throw BEDROCK_DETAILED_EXCEPTION("Could not initialize Margo"); - margo_enable_remote_shutdown(self->m_mid); - self->m_engine = tl::engine(self->m_mid); - setupMargoLoggingForInstance(self->m_mid); - // fill the m_pools array - size_t num_pools = margo_get_num_pools(self->m_mid); - for(unsigned i=0; i < num_pools; i++) { - margo_pool_info info; - if(HG_SUCCESS != margo_find_pool_by_index(self->m_mid, i, &info)) - throw BEDROCK_DETAILED_EXCEPTION( - "Failed to retrieve pool information from Margo instance"); - auto pool_entry = std::make_shared(info.name, info.pool); - self->m_pools.emplace_back(pool_entry); - } - // fill the m_xstreams array - size_t num_es = margo_get_num_xstreams(self->m_mid); - for(unsigned i=0; i < num_es; i++) { - margo_xstream_info info; - if(HG_SUCCESS != margo_find_xstream_by_index(self->m_mid, i, &info)) - throw BEDROCK_DETAILED_EXCEPTION( - "Failed to retrieve xstream information from Margo instance"); - auto es_entry = std::make_shared(info.name, info.xstream); - self->m_xstreams.emplace_back(es_entry); - } + self->m_engine = tl::engine{address.c_str(), MARGO_SERVER_MODE, &args}; + self->m_engine.enable_remote_shutdown(); + setupMargoLoggingForInstance(self->m_engine.get_margo_instance()); } // LCOV_EXCL_START @@ -73,10 +49,10 @@ MargoManager::operator bool() const { return static_cast(self); } margo_instance_id MargoManager::getMargoInstance() const { if(!self) return MARGO_INSTANCE_NULL; auto guard = std::unique_lock(self->m_mtx); - return self->m_mid; + return self->m_engine.get_margo_instance(); } -tl::engine MargoManager::getThalliumEngine() const { +const tl::engine& MargoManager::getThalliumEngine() const { auto guard = std::unique_lock(self->m_mtx); return self->m_engine; } @@ -88,244 +64,166 @@ std::string MargoManager::getCurrentConfig() const { std::shared_ptr MargoManager::getDefaultHandlerPool() const { auto guard = std::unique_lock(self->m_mtx); - ABT_pool p; - int ret = margo_get_handler_pool(self->m_mid, &p); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not get handler pool from Margo instance"); + try { + auto pool = self->m_engine.get_handler_pool(); + auto name = self->m_engine.pools()[pool].name(); + return std::make_shared(self->m_engine, name, pool); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_pools.begin(), self->m_pools.end(), - [p](std::shared_ptr& entry) { - return entry->getHandle() == p; - }); - return *it; } std::shared_ptr MargoManager::getPool(const std::string& name) const { - auto guard = std::unique_lock(self->m_mtx); - margo_pool_info info = {ABT_POOL_NULL,"",0}; - hg_return_t ret = margo_find_pool_by_name(self->m_mid, name.c_str(), &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool \"{}\" from Margo instance", - name); + try { + auto guard = std::unique_lock(self->m_mtx); + auto pool = self->m_engine.pools()[name]; + return std::make_shared(self->m_engine, pool.name(), pool); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_pools.begin(), self->m_pools.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.pool; - }); - return *it; } std::shared_ptr MargoManager::getPool(uint32_t index) const { - auto guard = std::unique_lock(self->m_mtx); - margo_pool_info info = {ABT_POOL_NULL,"",0}; - hg_return_t ret = margo_find_pool_by_index(self->m_mid, index, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool at index {} from Margo instance", - index); + try { + auto guard = std::unique_lock(self->m_mtx); + auto pool = self->m_engine.pools()[index]; + return std::make_shared(self->m_engine, pool.name(), pool); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_pools.begin(), self->m_pools.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.pool; - }); - return *it; } -std::shared_ptr MargoManager::getPool(ABT_pool pool) const { - auto guard = std::unique_lock(self->m_mtx); - margo_pool_info info = {ABT_POOL_NULL,"",0}; - hg_return_t ret = margo_find_pool_by_handle(self->m_mid, pool, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool from its ABT_pool handle in Margo instance"); +std::shared_ptr MargoManager::getPool(ABT_pool abt_pool) const { + try { + auto guard = std::unique_lock(self->m_mtx); + auto pool = self->m_engine.pools()[tl::pool{abt_pool}]; + return std::make_shared(self->m_engine, pool.name(), pool); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_pools.begin(), self->m_pools.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.pool; - }); - return *it; } size_t MargoManager::getNumPools() const { auto guard = std::unique_lock(self->m_mtx); - return margo_get_num_pools(self->m_mid); + return self->m_engine.pools().size(); } std::shared_ptr MargoManager::addPool(const std::string& config) { auto guard = std::unique_lock(self->m_mtx); + auto mid = self->m_engine.get_margo_instance(); margo_pool_info info; - hg_return_t ret = margo_add_pool_from_json( - self->m_mid, config.c_str(), &info); + hg_return_t ret = margo_add_pool_from_json(mid, config.c_str(), &info); if (ret != HG_SUCCESS) { throw BEDROCK_DETAILED_EXCEPTION( - "Could not add pool to Margo instance"); + "Could not add pool to Margo instance"); } - auto pool_entry = std::make_shared(info.name, info.pool); - self->m_pools.push_back(pool_entry); - return pool_entry; + return std::make_shared(self->m_engine, info.name, tl::pool{info.pool}); } void MargoManager::removePool(uint32_t index) { auto guard = std::unique_lock(self->m_mtx); - margo_pool_info info; - hg_return_t ret = margo_find_pool_by_index(self->m_mid, index, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool at index {} from Margo instance", - index); + try { + self->m_engine.pools().remove(index); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - guard.unlock(); - removePool(info.pool); } void MargoManager::removePool(const std::string& name) { auto guard = std::unique_lock(self->m_mtx); - auto it = std::find_if(self->m_pools.begin(), self->m_pools.end(), - [&name](auto& p) { return p->getName() == name; }); - if(it == self->m_pools.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool named \"{}\" known to Bedrock", name); - } - if(it->use_count() != 1) { - throw BEDROCK_DETAILED_EXCEPTION( - "Pool \"{}\" is still in use by some dependencies", name); - } - hg_return_t ret = margo_remove_pool_by_name(self->m_mid, name.c_str()); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not remove pool \"{}\" from Margo instance", name); + try { + self->m_engine.pools().remove(name); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - self->m_pools.erase(it); } void MargoManager::removePool(ABT_pool pool) { auto guard = std::unique_lock(self->m_mtx); - margo_pool_info info; - hg_return_t ret = margo_find_pool_by_handle(self->m_mid, pool, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find pool from its ABT_pool handle in Margo instance"); + try { + self->m_engine.pools().remove(tl::pool{pool}); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - guard.unlock(); - removePool(info.name); } std::shared_ptr MargoManager::getXstream(const std::string& name) const { auto guard = std::unique_lock(self->m_mtx); - margo_xstream_info info = {ABT_XSTREAM_NULL,"",0}; - hg_return_t ret = margo_find_xstream_by_name(self->m_mid, name.c_str(), &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream \"{}\" from Margo instance", - name); + try { + auto es = self->m_engine.xstreams()[name]; + return std::make_shared(self->m_engine, es.name(), es); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_xstreams.begin(), self->m_xstreams.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.xstream; - }); - return *it; } std::shared_ptr MargoManager::getXstream(uint32_t index) const { auto guard = std::unique_lock(self->m_mtx); - margo_xstream_info info = {ABT_XSTREAM_NULL,"",0}; - hg_return_t ret = margo_find_xstream_by_index(self->m_mid, index, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream at index {} from Margo instance", - index); + try { + auto es = self->m_engine.xstreams()[index]; + return std::make_shared(self->m_engine, es.name(), es); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_xstreams.begin(), self->m_xstreams.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.xstream; - }); - return *it; } -std::shared_ptr MargoManager::getXstream(ABT_xstream xstream) const { +std::shared_ptr MargoManager::getXstream(ABT_xstream abt_es) const { auto guard = std::unique_lock(self->m_mtx); - margo_xstream_info info = {ABT_XSTREAM_NULL,"",0}; - hg_return_t ret = margo_find_xstream_by_handle(self->m_mid, xstream, &info); - if (ret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream from its ABT_xstream handle in Margo instance"); + try { + auto es = self->m_engine.xstreams()[tl::xstream{abt_es}]; + return std::make_shared(self->m_engine, es.name(), es); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - auto it = std::find_if(self->m_xstreams.begin(), self->m_xstreams.end(), - [&info](std::shared_ptr& entry) { - return entry->getHandle() == info.xstream; - }); - return *it; } size_t MargoManager::getNumXstreams() const { auto guard = std::unique_lock(self->m_mtx); - return margo_get_num_xstreams(self->m_mid); + try { + return self->m_engine.xstreams().size(); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; + } } std::shared_ptr MargoManager::addXstream(const std::string& config) { auto guard = std::unique_lock(self->m_mtx); + auto mid = self->m_engine.get_margo_instance(); margo_xstream_info info; - hg_return_t hret = margo_add_xstream_from_json( - self->m_mid, config.c_str(), &info); - if (hret != HG_SUCCESS) { + hg_return_t ret = margo_add_xstream_from_json(mid, config.c_str(), &info); + if (ret != HG_SUCCESS) { throw BEDROCK_DETAILED_EXCEPTION( - "Could not add xstream to Margo instance (margo_add_xstream_from_json returned {})", - std::to_string(hret)); + "Could not add xstream to Margo instance"); } - auto entry = std::make_shared(info.name, info.xstream); - self->m_xstreams.push_back(entry); - return entry; + return std::make_shared(self->m_engine, info.name, tl::xstream{info.xstream}); } void MargoManager::removeXstream(uint32_t index) { auto guard = std::unique_lock(self->m_mtx); - margo_xstream_info info; - hg_return_t hret = margo_find_xstream_by_index(self->m_mid, index, &info); - if (hret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream at index {} from Margo instance " - "(margo_find_xstream_by_index returned {})", - index, std::to_string(hret)); + try { + self->m_engine.xstreams().remove(index); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - guard.unlock(); - removeXstream(info.xstream); } void MargoManager::removeXstream(const std::string& name) { auto guard = std::unique_lock(self->m_mtx); - auto it = std::find_if(self->m_xstreams.begin(), self->m_xstreams.end(), - [&name](auto& es) { return es->getName() == name; }); - if(it == self->m_xstreams.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream named \"{}\" known to Bedrock", name); - } - if(it->use_count() != 1) { - throw BEDROCK_DETAILED_EXCEPTION( - "Xstream \"{}\" is still in use by some dependencies", name); + try { + self->m_engine.xstreams().remove(name); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - hg_return_t hret = margo_remove_xstream_by_name(self->m_mid, name.c_str()); - if (hret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not remove xstream \"{}\" from Margo instance " - "(margo_remove_xstream_by_name returned {})", - name, std::to_string(hret)); - } - self->m_xstreams.erase(it); } -void MargoManager::removeXstream(ABT_xstream xstream) { +void MargoManager::removeXstream(ABT_xstream es) { auto guard = std::unique_lock(self->m_mtx); - margo_xstream_info info; - hg_return_t hret = margo_find_xstream_by_handle(self->m_mid, xstream, &info); - if (hret != HG_SUCCESS) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find xstream from its ABT_xstream handle in Margo instance " - "(margo_find_xstream_by_handle returned {})", std::to_string(hret)); + try { + self->m_engine.xstreams().remove(tl::xstream{es}); + } catch(const tl::exception& ex) { + throw Exception{"{}", ex.what()}; } - guard.unlock(); - removeXstream(info.name); } + } // namespace bedrock diff --git a/src/MargoManagerImpl.hpp b/src/MargoManagerImpl.hpp index 8cc686f..69f3905 100644 --- a/src/MargoManagerImpl.hpp +++ b/src/MargoManagerImpl.hpp @@ -20,39 +20,49 @@ using nlohmann::json; struct PoolRef : public NamedDependency { - PoolRef(std::string name, ABT_pool pool) - : NamedDependency( - std::move(name), - "pool", pool, - std::function()) {} + tl::engine engine; + PoolRef(tl::engine e, std::string name, tl::pool pool) + : NamedDependency(std::move(name), "pool", std::move(pool)) + , engine{std::move(e)} { + engine.pools().ref_incr(getHandle()); + } + + PoolRef(const PoolRef&) = delete; + PoolRef(PoolRef&&) = delete; + + ~PoolRef() { + engine.pools().release(getHandle()); + } }; struct XstreamRef : public NamedDependency { - XstreamRef(std::string name, ABT_xstream xstream) - : NamedDependency( - std::move(name), - "xstream", xstream, - std::function()) {} + tl::engine engine; + XstreamRef(tl::engine e, std::string name, tl::xstream es) + : NamedDependency(std::move(name), "xstream", std::move(es)) + , engine{std::move(e)} { + engine.xstreams().ref_incr(getHandle()); + } + + XstreamRef(const XstreamRef&) = delete; + XstreamRef(XstreamRef&&) = delete; + + ~XstreamRef() { + engine.xstreams().release(getHandle()); + } }; class MargoManagerImpl { public: - tl::mutex m_mtx; - margo_instance_id m_mid; - tl::engine m_engine; - - // to keep track of who is using which pool and xstream, - // we keep a shared_ptr to a PoolRef/XstreamRef with just - // the name of the pool/xstream and its handle. - std::vector> m_xstreams; - std::vector> m_pools; + tl::mutex m_mtx; + tl::engine m_engine; json makeConfig() const { - char* str = margo_get_config_opt(m_mid, MARGO_CONFIG_USE_NAMES); + auto mid = m_engine.get_margo_instance(); + char* str = margo_get_config_opt(mid, MARGO_CONFIG_USE_NAMES); auto config = json::parse(str); free(str); return config; diff --git a/src/ProviderManager.cpp b/src/ProviderManager.cpp index 175b9ae..3059eb4 100644 --- a/src/ProviderManager.cpp +++ b/src/ProviderManager.cpp @@ -4,8 +4,8 @@ * See COPYRIGHT in top-level directory. */ #include -#include -#include +#include +#include #include #include @@ -30,7 +30,7 @@ ProviderManager::ProviderManager(const MargoManager& margo, uint16_t provider_id, std::shared_ptr pool) : self(std::make_shared(margo.getThalliumEngine(), - provider_id, tl::pool(pool->getHandle()))) { + provider_id, tl::pool(pool->getHandle()))) { self->m_margo_manager = margo; self->m_jx9_manager = jx9; } @@ -86,65 +86,6 @@ std::shared_ptr ProviderManager::getProvider(size_t index) c return self->m_providers[index]; } -std::shared_ptr -ProviderManager::registerProvider( - const std::string& name, const std::string& type, uint16_t provider_id, - std::shared_ptr pool, const json& config, - const ResolvedDependencyMap& dependencies, - const std::vector& tags) { - - std::shared_ptr entry; - auto service_factory = ModuleContext::getServiceFactory(type); - if (!service_factory) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find service factory for provider type \"{}\"", type); - } - - { - std::lock_guard lock(self->m_providers_mtx); - auto it = self->resolveSpec(name); - if (it != self->m_providers.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Name \"{}\" already used by another provider", name); - } - - if (provider_id == std::numeric_limits::max()) - provider_id = self->getAvailableProviderID(); - - it = std::find_if(self->m_providers.begin(), self->m_providers.end(), - [provider_id](const auto& p) { return p->getProviderID() == provider_id; }); - if (it != self->m_providers.end()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Another provider already uses provider ID {}", provider_id); - } - - auto margo = MargoManager(self->m_margo_manager); - - FactoryArgs args; - args.name = name; - args.mid = margo.getMargoInstance(); - args.engine = margo.getThalliumEngine(); - args.pool = pool->getHandle(); - args.config = config.is_null() ? std::string{"{}"} : config.dump(); - args.tags = tags; - args.dependencies = dependencies; - args.provider_id = provider_id; - - auto handle = service_factory->registerProvider(args); - - entry = std::make_shared( - name, type, provider_id, handle, service_factory, pool, - std::move(dependencies), tags); - - spdlog::trace("Registered provider {} of type {} with provider id {}", - name, type, provider_id); - - self->m_providers.push_back(entry); - } - self->m_providers_cv.notify_all(); - return entry; -} - void ProviderManager::deregisterProvider(const std::string& spec) { std::lock_guard lock(self->m_providers_mtx); auto it = self->resolveSpec(spec); @@ -161,17 +102,12 @@ ProviderManager::addProviderFromJSON(const json& description) { throw BEDROCK_DETAILED_EXCEPTION("No DependencyFinder set in ProviderManager"); } auto dependencyFinder = DependencyFinder(self->m_dependency_finder); - static const json configSchema = R"( { "$schema": "https://json-schema.org/draft/2019-09/schema", "type": "object", "properties": { "name": {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - "pool": {"oneOf": [ - {"type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, - {"type": "integer", "minimum": 0 } - ]}, "provider_id": {"type": "integer", "minimum": 0, "maximum": 65535}, "type": {"type": "string"}, "tags": { @@ -195,55 +131,35 @@ ProviderManager::addProviderFromJSON(const json& description) { static const JsonValidator validator{configSchema}; validator.validate(description, "ProviderManager"); - auto& name = description["name"].get_ref(); auto& type = description["type"].get_ref(); - auto provider_id = description.value("provider_id", std::numeric_limits::max()); - - auto service_factory = ModuleContext::getServiceFactory(type); - if (!service_factory) { - throw BEDROCK_DETAILED_EXCEPTION( - "Could not find service factory for provider type \"{}\"", type); - } - - auto config = description.value("config", json::object()); - auto configStr = config.dump(); - - // find pool - std::shared_ptr pool; - if(description.contains("pool") && description["pool"].is_number()) { - pool = MargoManager(self->m_margo_manager) - .getPool(description["pool"].get()); - } else { - pool = MargoManager(self->m_margo_manager) - .getPool(description.value("pool", "__primary__")); - } - - std::vector tags; - for(auto& tag : description.value("tags", json::array())) { - tags.push_back(tag.get()); - } + ComponentArgs args; + args.name = description["name"]; + args.provider_id = description.value("provider_id", std::numeric_limits::max()); + args.config = description.value("config", json::object()).dump(); + args.engine = MargoManager{self->m_margo_manager}.getThalliumEngine(); + for(auto& tag : description.value("tags", json::array())) + args.tags.push_back(tag.get()); auto deps_from_config = description.value("dependencies", json::object()); - ResolvedDependencyMap resolved_dependency_map; + auto requested_dependencies = ModuleManager::getDependencies(type, args); + auto& resolved_dependency_map = args.dependencies; - for (const auto& dependency : service_factory->getProviderDependencies(configStr.c_str())) { + for (const auto& dependency : requested_dependencies) { spdlog::trace("Resolving dependency {}", dependency.name); if (deps_from_config.contains(dependency.name)) { auto dep_config = deps_from_config[dependency.name]; - if (!(dependency.flags & BEDROCK_ARRAY)) { // dependency should be a string + if (!(dependency.is_array)) { // dependency should be a string if (dep_config.is_array() && dep_config.size() == 1) { // an array of length 1 can be converted into a single string dep_config = dep_config[0]; } if (!dep_config.is_string()) { - throw BEDROCK_DETAILED_EXCEPTION("Dependency \"{}\" should be a string", - dependency.name); + throw BEDROCK_DETAILED_EXCEPTION( + "Dependency \"{}\" should be a string", dependency.name); } auto dep_handle = dependencyFinder.find( - dependency.type, BEDROCK_GET_KIND_FROM_FLAG(dependency.flags), - dep_config.get(), nullptr); - resolved_dependency_map[dependency.name].is_array = false; - resolved_dependency_map[dependency.name].dependencies.push_back(dep_handle); + dependency.type, dep_config.get(), nullptr); + resolved_dependency_map[dependency.name].push_back(dep_handle); } else { // dependency is an array if (dep_config.is_string()) { @@ -253,27 +169,56 @@ ProviderManager::addProviderFromJSON(const json& description) { dep_config = tmp_array; } if (!dep_config.is_array()) { - throw BEDROCK_DETAILED_EXCEPTION("Dependency \"{}\" should be an array", + throw BEDROCK_DETAILED_EXCEPTION( + "Dependency \"{}\" should be an array", dependency.name); } std::vector deps; for (const auto& elem : dep_config) { auto dep_handle = dependencyFinder.find( - dependency.type, BEDROCK_GET_KIND_FROM_FLAG(dependency.flags), - elem.get(), nullptr); - resolved_dependency_map[dependency.name].is_array = true; - resolved_dependency_map[dependency.name].dependencies.push_back(dep_handle); + dependency.type, elem.get(), nullptr); + resolved_dependency_map[dependency.name].push_back(dep_handle); } } - } else if (dependency.flags & BEDROCK_REQUIRED) { + } else if (dependency.is_required) { throw BEDROCK_DETAILED_EXCEPTION( - "Missing dependency \"{}\" of type \"{}\" in provider configuration", - dependency.name, dependency.type); + "Missing dependency \"{}\" of type \"{}\" in provider configuration", + dependency.name, dependency.type); } } - return registerProvider(name, type, provider_id, pool, config, - resolved_dependency_map, tags); + std::shared_ptr entry; + { + std::unique_lock lock(self->m_providers_mtx); + auto it = self->resolveSpec(args.name); + if (it != self->m_providers.end()) { + throw BEDROCK_DETAILED_EXCEPTION( + "Name \"{}\" already used by another provider", args.name); + } + + if (args.provider_id == std::numeric_limits::max()) + args.provider_id = self->getAvailableProviderID(); + + it = std::find_if(self->m_providers.begin(), self->m_providers.end(), + [&](const auto& p) { return p->getProviderID() == args.provider_id; }); + if (it != self->m_providers.end()) { + throw BEDROCK_DETAILED_EXCEPTION( + "Another provider already uses provider ID {}", args.provider_id); + } + + auto handle = ModuleManager::createComponent(type, args); + + entry = std::make_shared( + args.name, type, args.provider_id, handle, + requested_dependencies, args.dependencies, args.tags); + + spdlog::trace("Registered provider {} of type {} with provider id {}", + args.name, type, args.provider_id); + + self->m_providers.push_back(entry); + } + self->m_providers_cv.notify_all(); + return entry; } void ProviderManager::addProviderListFromJSON(const json& list) { @@ -288,24 +233,6 @@ void ProviderManager::addProviderListFromJSON(const json& list) { } } -void ProviderManager::changeProviderPool(const std::string& provider, - const std::string& pool_name) { - // find the provider - std::lock_guard lock(self->m_providers_mtx); - auto it = self->resolveSpec(provider); - if (it == self->m_providers.end()) - throw BEDROCK_DETAILED_EXCEPTION("Provider with spec \"{}\" not found", provider); - // find the pool - auto margo_manager = MargoManager(self->m_margo_manager); - auto pool = margo_manager.getPool(pool_name); - if(!pool) { - throw BEDROCK_DETAILED_EXCEPTION("Could not find pool named \"{}\"", pool_name); - } - // call the provider's change_pool callback - (*it)->factory->changeProviderPool((*it)->getHandle(), pool->getHandle()); - (*it)->pool = pool; -} - void ProviderManager::migrateProvider( const std::string& provider, const std::string& dest_addr, @@ -317,10 +244,9 @@ void ProviderManager::migrateProvider( auto it = self->resolveSpec(provider); if (it == self->m_providers.end()) throw BEDROCK_DETAILED_EXCEPTION("Provider with spec \"{}\" not found", provider); - // call the provider's migrateProvider callback + ComponentPtr theProvider = (*it)->getHandle(); try { - (*it)->factory->migrateProvider( - (*it)->getHandle(), + theProvider->migrate( dest_addr.c_str(), dest_provider_id, migration_config.c_str(), remove_source); @@ -339,13 +265,12 @@ void ProviderManager::snapshotProvider( auto it = self->resolveSpec(provider); if (it == self->m_providers.end()) throw BEDROCK_DETAILED_EXCEPTION("Provider with spec \"{}\" not found", provider); - // call the provider's snapshotProvider callback + ComponentPtr theProvider = (*it)->getHandle(); try { - (*it)->factory->snapshotProvider( - (*it)->getHandle(), - dest_path.c_str(), - snapshot_config.c_str(), - remove_source); + theProvider->snapshot( + dest_path.c_str(), + snapshot_config.c_str(), + remove_source); } catch(const std::exception& ex) { throw Exception{ex.what()}; } @@ -360,12 +285,11 @@ void ProviderManager::restoreProvider( auto it = self->resolveSpec(provider); if (it == self->m_providers.end()) throw BEDROCK_DETAILED_EXCEPTION("Provider with spec \"{}\" not found", provider); - // call the provider's restoreProvider callback + ComponentPtr theProvider = (*it)->getHandle(); try { - (*it)->factory->restoreProvider( - (*it)->getHandle(), - src_path.c_str(), - restore_config.c_str()); + theProvider->restore( + src_path.c_str(), + restore_config.c_str()); } catch(const std::exception& ex) { throw Exception{ex.what()}; } diff --git a/src/ProviderManagerImpl.hpp b/src/ProviderManagerImpl.hpp index 3e43ca6..e33b3dc 100644 --- a/src/ProviderManagerImpl.hpp +++ b/src/ProviderManagerImpl.hpp @@ -10,7 +10,7 @@ #include "bedrock/DependencyFinder.hpp" #include "bedrock/DependencyMap.hpp" #include "bedrock/RequestResult.hpp" -#include "bedrock/AbstractServiceFactory.hpp" +#include "bedrock/AbstractComponent.hpp" #include "bedrock/ProviderDescriptor.hpp" #include "bedrock/Jx9Manager.hpp" #include "bedrock/Exception.hpp" @@ -34,49 +34,51 @@ class LocalProvider : public ProviderDependency { public: - std::shared_ptr pool; - ResolvedDependencyMap dependencies; - AbstractServiceFactory* factory = nullptr; - std::vector tags; + std::vector requested_dependencies; + ResolvedDependencyMap resolved_dependencies; + std::vector tags; LocalProvider( - std::string name, std::string type, uint16_t provider_id, - void* handle, AbstractServiceFactory* factory, - std::shared_ptr pool, - ResolvedDependencyMap deps, - std::vector _tags) - : ProviderDependency(std::move(name), std::move(type), handle, - [factory](void* handle) { - if(factory) factory->deregisterProvider(handle); - }, provider_id) - , pool(std::move(pool)) - , dependencies(std::move(deps)) - , factory(factory) - , tags(std::move(_tags)) - {} + std::string name, std::string type, uint16_t provider_id, ComponentPtr ptr, + std::vector req_deps, ResolvedDependencyMap res_deps, + std::vector _tags) + : ProviderDependency(std::move(name), std::move(type), ptr, provider_id) + , requested_dependencies(std::move(req_deps)) + , resolved_dependencies(std::move(res_deps)) + , tags(std::move(_tags)) + { + std::cerr << "Created LocalProvider with name " << getName() + << ", type " << getType() << ", provider id " << provider_id + << ", and the following dependency map:" << std::endl; + for(auto& p : resolved_dependencies) { + std::cerr << p.first << ": " << std::endl; + for(auto d : p.second) { + std::cerr << " " << d->getName() << std::endl; + } + } + } json makeConfig() const { + ComponentPtr ptr = getHandle(); auto c = json::object(); c["name"] = getName(); c["type"] = getType(); c["provider_id"] = getProviderID(); - c["pool"] = pool->getName(); - c["config"] = json::parse(factory->getProviderConfig(getHandle())); + c["config"] = json::parse(ptr->getConfig()); c["tags"] = json::array(); for(auto& t : tags) c["tags"].push_back(t); c["dependencies"] = json::object(); auto& d = c["dependencies"]; - for (auto& p : dependencies) { - auto& dep_name = p.first; - auto& dep_group = p.second; - if (dep_group.dependencies.size() == 0) continue; - if (!dep_group.is_array) { - d[dep_name] = dep_group.dependencies[0]->getName(); - } else { - d[dep_name] = json::array(); - for (auto& x : dep_group.dependencies) { - d[dep_name].push_back(x->getName()); + for (auto& dep : requested_dependencies) { + auto res_dep = resolved_dependencies.find(dep.name); + if(res_dep == resolved_dependencies.end()) continue; + if(dep.is_array) { + d[dep.name] = json::array(); + for(auto& x : res_dep->second) { + d[dep.name].push_back(x->getName()); } + } else { + d[dep.name] = res_dep->second[0]->getName(); } } return c; @@ -99,7 +101,6 @@ class ProviderManagerImpl tl::auto_remote_procedure m_lookup_provider; tl::auto_remote_procedure m_load_module; tl::auto_remote_procedure m_start_provider; - tl::auto_remote_procedure m_change_provider_pool; tl::auto_remote_procedure m_migrate_provider; tl::auto_remote_procedure m_snapshot_provider; tl::auto_remote_procedure m_restore_provider; @@ -113,8 +114,6 @@ class ProviderManagerImpl &ProviderManagerImpl::loadModuleRPC, pool)), m_start_provider(define("bedrock_start_provider", &ProviderManagerImpl::startProviderRPC, pool)), - m_change_provider_pool(define("bedrock_change_provider_pool", - &ProviderManagerImpl::changeProviderPoolRPC, pool)), m_migrate_provider(define("bedrock_migrate_provider", &ProviderManagerImpl::migrateProviderRPC, pool)), m_snapshot_provider(define("bedrock_snapshot_provider", @@ -199,12 +198,12 @@ class ProviderManagerImpl } } - void loadModuleRPC(const tl::request& req, const std::string& name, + void loadModuleRPC(const tl::request& req, const std::string& path) { RequestResult result; tl::auto_respond auto_respond_with{req, result}; try { - ModuleContext::loadModule(name, path); + ModuleManager::loadModule(path); result.success() = true; result.value() = true; } catch (const Exception& e) { @@ -226,19 +225,6 @@ class ProviderManagerImpl } } - void changeProviderPoolRPC(const tl::request& req, const std::string& name, - const std::string& pool) { - RequestResult result; - tl::auto_respond auto_respond_with{req, result}; - auto manager = ProviderManager(shared_from_this()); - try { - manager.changeProviderPool(name, pool); - } catch (Exception& ex) { - result.success() = false; - result.error() = ex.what(); - } - } - void migrateProviderRPC(const tl::request& req, const std::string& name, const std::string& dest_addr, diff --git a/src/Server.cpp b/src/Server.cpp index 064fbe0..b6c3846 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -5,9 +5,8 @@ */ #include #include -#include +#include #include -#include #include #include #include @@ -143,32 +142,19 @@ Server::Server(const std::string& address, const std::string& configString, self->m_provider_manager = providerManager; spdlog::trace("ProviderManager initialized"); - // Initializing the client manager - spdlog::trace("Initializing ClientManager"); - auto clientManager - = ClientManager(margoMgr, jx9Manager, bedrock_provider_id, bedrock_pool); - self->m_client_manager = clientManager; - spdlog::trace("ClientManager initialized"); - // Initialize the module context spdlog::trace("Initialize ModuleContext"); auto librariesConfig = config["libraries"].dump(); - ModuleContext::loadModulesFromJSON(librariesConfig); + ModuleManager::loadModulesFromJSON(librariesConfig); spdlog::trace("ModuleContext initialized"); // Initializing dependency finder spdlog::trace("Initializing DependencyFinder"); - auto dependencyFinder = DependencyFinder(mpi, margoMgr, providerManager, clientManager); + auto dependencyFinder = DependencyFinder(mpi, margoMgr, providerManager); self->m_dependency_finder = dependencyFinder; self->m_dependency_finder->m_timeout = dependency_timeout; spdlog::trace("DependencyFinder initialized"); - // Creating clients - spdlog::trace("Initializing clients"); - clientManager.setDependencyFinder(dependencyFinder); - auto& clientManagerConfig = config["clients"]; - clientManager.addClientListFromJSON(clientManagerConfig); - // Starting up providers spdlog::trace("Initializing providers"); auto& providerManagerConfig = config["providers"]; @@ -193,20 +179,14 @@ ProviderManager Server::getProviderManager() const { return self->m_provider_manager; } -ClientManager Server::getClientManager() const { - return self->m_client_manager; -} - -void Server::onPreFinalize(void* uargs) { +void Server::onPreFinalize() { spdlog::trace("Calling Server's pre-finalize callback"); - auto server = reinterpret_cast(uargs); - if(server->self) { - if(server->self->m_provider_manager) - server->self->m_provider_manager.reset(); + if(self && self->m_provider_manager) { + self->m_provider_manager.reset(); } } -void Server::onFinalize(void* uargs) { +void Server::onFinalize() { spdlog::trace("Calling Server's finalize callback"); } @@ -215,19 +195,17 @@ std::string Server::getCurrentConfig() const { } void Server::waitForFinalize() { - margo_push_finalize_callback(self->m_margo_manager->m_mid, - &Server::onFinalize, this); - margo_push_prefinalize_callback(self->m_margo_manager->m_mid, - &Server::onPreFinalize, this); - margo_wait_for_finalize(self->m_margo_manager->m_mid); + auto engine = getMargoManager().getThalliumEngine(); + engine.push_finalize_callback([this]() { onFinalize(); }); + engine.push_prefinalize_callback([this]() { onPreFinalize(); }); + engine.wait_for_finalize(); } void Server::finalize() { - margo_push_finalize_callback(self->m_margo_manager->m_mid, - &Server::onFinalize, this); - margo_push_prefinalize_callback(self->m_margo_manager->m_mid, - &Server::onPreFinalize, this); - margo_finalize_and_wait(self->m_margo_manager->m_mid); + auto engine = getMargoManager().getThalliumEngine(); + engine.push_finalize_callback([this]() { onFinalize(); }); + engine.push_prefinalize_callback([this]() { onPreFinalize(); }); + engine.finalize_and_wait(); } } // namespace bedrock diff --git a/src/ServerImpl.hpp b/src/ServerImpl.hpp index 512665f..62e4e5c 100644 --- a/src/ServerImpl.hpp +++ b/src/ServerImpl.hpp @@ -8,13 +8,12 @@ #include "MargoManagerImpl.hpp" #include "ProviderManagerImpl.hpp" -#include "ClientManagerImpl.hpp" #include "DependencyFinderImpl.hpp" #include "Jx9ManagerImpl.hpp" #include "MPIEnvImpl.hpp" #include "bedrock/Jx9Manager.hpp" #include "bedrock/RequestResult.hpp" -#include "bedrock/ModuleContext.hpp" +#include "bedrock/ModuleManager.hpp" #include #include #include @@ -31,7 +30,6 @@ class ServerImpl : public tl::provider { std::shared_ptr m_mpi; std::shared_ptr m_jx9_manager; std::shared_ptr m_margo_manager; - std::shared_ptr m_client_manager; std::shared_ptr m_provider_manager; std::shared_ptr m_dependency_finder; std::shared_ptr m_pool; @@ -50,7 +48,7 @@ class ServerImpl : public tl::provider { : tl::provider(margo->m_engine, provider_id, "bedrock"), m_margo_manager(std::move(margo)), m_pool(pool), - m_tl_pool(pool->getHandle()), + m_tl_pool(pool->getHandle()), m_get_config_rpc( define("bedrock_get_config", &ServerImpl::getConfigRPC, m_tl_pool)), m_query_config_rpc( @@ -77,9 +75,8 @@ class ServerImpl : public tl::provider { json makeConfig() const { auto config = json::object(); config["margo"] = m_margo_manager->makeConfig(); - config["clients"] = m_client_manager->makeConfig(); config["providers"] = m_provider_manager->makeConfig(); - config["libraries"] = json::parse(ModuleContext::getCurrentConfig()); + config["libraries"] = json::parse(ModuleManager::getCurrentConfig()); config["bedrock"] = json::object(); config["bedrock"]["pool"] = m_pool->getName(); config["bedrock"]["provider_id"] = get_provider_id(); diff --git a/src/ServiceHandle.cpp b/src/ServiceHandle.cpp index 69420af..5931737 100644 --- a/src/ServiceHandle.cpp +++ b/src/ServiceHandle.cpp @@ -70,12 +70,12 @@ tl::provider_handle ServiceHandle::providerHandle() const { } \ } while(0) -void ServiceHandle::loadModule(const std::string& name, const std::string& path, +void ServiceHandle::loadModule(const std::string& path, AsyncRequest* req) const { if (not self) throw BEDROCK_DETAILED_EXCEPTION("Invalid bedrock::ServiceHandle object"); auto& rpc = self->m_client->m_load_module; auto& ph = self->m_ph; - SEND_RPC_WITH_BOOL_RESULT(name, path); + SEND_RPC_WITH_BOOL_RESULT(path); } void ServiceHandle::addProvider(const std::string& description, diff --git a/tests/Client.cpp b/tests/Client.cpp index 111ea50..9b3d7aa 100644 --- a/tests/Client.cpp +++ b/tests/Client.cpp @@ -14,7 +14,6 @@ TEST_CASE("Tests various object creation and removal via a ServiceHandle", "[ser auto engine = server.getMargoManager().getThalliumEngine(); bedrock::Client client(engine); auto serviceHandle = client.makeServiceHandle(engine.self(), 0); - SECTION("Add and remove pool remotely") { // add a pool called "my_pool1", synchronously serviceHandle.addPool("{\"name\":\"my_pool1\",\"kind\":\"fifo_wait\",\"access\":\"mpmc\"}"); @@ -107,24 +106,28 @@ TEST_CASE("Tests various object creation and removal via a ServiceHandle", "[ser } SECTION("Load a library") { + auto server_config = server.getCurrentConfig(); + REQUIRE(server_config.find("./libModuleA.so") == std::string::npos); + REQUIRE(server_config.find("./libModuleB.so") == std::string::npos); // load libModuleA.so synchronously - serviceHandle.loadModule("module_a", "./libModuleA.so"); - REQUIRE(bedrock::ModuleContext::getServiceFactory("module_a") != nullptr); + serviceHandle.loadModule("./libModuleA.so"); + server_config = server.getCurrentConfig(); + REQUIRE(server_config.find("./libModuleA.so") != std::string::npos); // load libModuleA.so asynchronously bedrock::AsyncRequest req; - serviceHandle.loadModule("module_b", "./libModuleB.so", &req); + serviceHandle.loadModule("./libModuleB.so", &req); req.wait(); - REQUIRE(bedrock::ModuleContext::getServiceFactory("module_b") != nullptr); - // load libModuleC.so, which does not exist + server_config = server.getCurrentConfig(); + REQUIRE(server_config.find("./libModuleB.so") != std::string::npos); + // load libModuleX.so, which does not exist REQUIRE_THROWS_AS( - serviceHandle.loadModule("module_x", "libModuleX.so"), + serviceHandle.loadModule("./libModuleX.so"), bedrock::Exception); } SECTION("Add and remove providers") { // load module_a - serviceHandle.loadModule("module_a", "./libModuleA.so"); - REQUIRE(bedrock::ModuleContext::getServiceFactory("module_a") != nullptr); + serviceHandle.loadModule("./libModuleA.so"); // create a provider of type module_a REQUIRE_NOTHROW(serviceHandle.addProvider(R"( {"name":"my_provider_a1", "type":"module_a", "provider_id":123})")); diff --git a/tests/InitInvalid.cpp b/tests/InitInvalid.cpp index 22d0f8e..c4aa8e6 100644 --- a/tests/InitInvalid.cpp +++ b/tests/InitInvalid.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include diff --git a/tests/InitJx9.cpp b/tests/InitJx9.cpp index 677e298..8f11055 100644 --- a/tests/InitJx9.cpp +++ b/tests/InitJx9.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include diff --git a/tests/InvalidConfigs.json b/tests/InvalidConfigs.json index 976a025..29519f2 100644 --- a/tests/InvalidConfigs.json +++ b/tests/InvalidConfigs.json @@ -6,12 +6,12 @@ { "test": "invalid type for library", - "input": {"libraries":{"module_a":123}} + "input": {"libraries":[123]} }, { "test": "library not found", - "input": {"libraries":{"module_a":"abc.so"}} + "input": {"libraries":["abc.so"]} }, @@ -37,113 +37,47 @@ { "test": "invalid type for provider name in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":true,"provider_id":123,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":true,"provider_id":123,"type":"module_a"}]} }, { "test": "invalid type for provider type in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"type":true}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider","provider_id":123,"type":true}]} }, { "test": "invalid type for provider_id in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":true,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider","provider_id":true,"type":"module_a"}]} }, { "test": "invalid provider_id value in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":-1,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider","provider_id":-1,"type":"module_a"}]} }, { "test": "invalid config type in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"type":"module_a","config":true}]} - }, - - { - "test": "invalid pool type in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"type":"module_a","pool":true}]} - }, - - { - "test": "invalid pool name in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"type":"module_a","pool":"abc"}]} - }, - - { - "test": "invalid pool index in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"type":"module_a","pool":1234}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider","provider_id":123,"type":"module_a","config":true}]} }, { "test": "provider definition without a name", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"provider_id":123,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"provider_id":123,"type":"module_a"}]} }, { "test": "empty provider name in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"","provider_id":123,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"","provider_id":123,"type":"module_a"}]} }, { "test": "two providers with the same name", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider","provider_id":1,"type":"module_a"},{"name":"my_provider","provider_id":2,"type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider","provider_id":1,"type":"module_a"},{"name":"my_provider","provider_id":2,"type":"module_a"}]} }, { "test": "two providers with the same provider id", - "input": {"libraries":{"module_a":"libModuleA.so"},"providers":[{"name":"my_provider1","provider_id":42,"type":"module_a"},{"name":"my_provider2","provider_id":42,"type":"module_a"}]} - }, - - - { - "test": "invalid type of client field", - "input": {"clients":true} - }, - - { - "test": "invalid type of client definition", - "input": {"clients":[true]} - }, - - { - "test": "no client type in client definition", - "input": {"clients":[{"name":"my_client"}]} - }, - - { - "test": "invalid client type in client definition", - "input": {"clients":[{"name":"my_client","type":"module_invalid"}]} - }, - - { - "test": "invalid type for client name in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"name":true,"type":"module_a"}]} - }, - - { - "test": "invalid type for client type in provider definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"name":"my_client","type":true}]} - }, - - { - "test": "invalid config type in client definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"name":"my_client","type":"module_a","config":true}]} - }, - - { - "test": "client definition without a name", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"type":"module_a"}]} - }, - - { - "test": "empty client name in client definition", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"name":"","type":"module_a"}]} - }, - - { - "test": "two clients with the same name", - "input": {"libraries":{"module_a":"libModuleA.so"},"clients":[{"name":"my_client","type":"module_a"},{"name":"my_client","type":"module_a"}]} + "input": {"libraries":["libModuleA.so"],"providers":[{"name":"my_provider1","provider_id":42,"type":"module_a"},{"name":"my_provider2","provider_id":42,"type":"module_a"}]} } ] diff --git a/tests/ValidConfigs.json b/tests/ValidConfigs.json index 861626a..f6cfa4e 100644 --- a/tests/ValidConfigs.json +++ b/tests/ValidConfigs.json @@ -2,36 +2,24 @@ { "test": "empty configuration", "input": {}, - "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"libraries":[],"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "using use_progress_thread and rpc_thread_count in Margo", "input": {"margo":{"use_progress_thread":true,"rpc_thread_count":2}}, - "output": {"bedrock":{"pool":"__pool_2__","provider_id":0},"clients":[],"libraries":{},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[]} + "output": {"bedrock":{"pool":"__pool_2__","provider_id":0},"libraries":[],"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_1__"},{"access":"mpmc","kind":"fifo_wait","name":"__pool_2__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}},{"name":"__xstream_1__","scheduler":{"pools":["__pool_1__"],"type":"basic_wait"}},{"name":"__xstream_2__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}},{"name":"__xstream_3__","scheduler":{"pools":["__pool_2__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__pool_1__","progress_timeout_ub_msec":100,"rpc_pool":"__pool_2__"},"providers":[]} }, { "test": "load a module library", - "input": {"libraries":{"module_a":"./libModuleA.so"}}, - "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "input": {"libraries":["./libModuleA.so"]}, + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"libraries":["./libModuleA.so"],"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} }, { "test": "instantiate a provider from module-a", - "input": {"libraries":{"module_a":"./libModuleA.so"},"providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} - }, - - { - "test": "instantiate a provider from module-a with simplified syntax", - "input": {"libraries.module_a":"./libModuleA.so","providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, - "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","pool":"__primary__","provider_id":123,"tags":[],"type":"module_a"}]} - }, - - { - "test": "instantiate a client from module-a", - "input": {"libraries":{"module_a":"./libModuleA.so"},"clients":[{"name":"my_client","type":"module_a"}]}, - "output": {"bedrock":{"pool":"__primary__","provider_id":0},"clients":[{"config":{},"dependencies":{},"name":"my_client","tags":[],"type":"module_a"}],"libraries":{"module_a":"./libModuleA.so"},"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[]} + "input": {"libraries":["./libModuleA.so"],"providers":[{"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]}, + "output": {"bedrock":{"pool":"__primary__","provider_id":0},"libraries":["./libModuleA.so"],"margo":{"argobots":{"abt_mem_max_num_stacks":8,"abt_thread_stacksize":2097152,"lazy_stack_alloc":false,"pools":[{"access":"mpmc","kind":"fifo_wait","name":"__primary__"}],"profiling_dir":".","xstreams":[{"name":"__primary__","scheduler":{"pools":["__primary__"],"type":"basic_wait"}}]},"enable_abt_profiling":false,"handle_cache_size":32,"progress_pool":"__primary__","progress_timeout_ub_msec":100,"rpc_pool":"__primary__"},"providers":[{"config":{},"dependencies":{},"name":"my_provider","provider_id":123,"tags":[],"type":"module_a"}]} } ] diff --git a/tests/modules/BaseModule.hpp b/tests/modules/BaseModule.hpp index 078fb54..a636e58 100644 --- a/tests/modules/BaseModule.hpp +++ b/tests/modules/BaseModule.hpp @@ -1,51 +1,28 @@ #include "Helpers.hpp" #include -class BaseServiceFactory : public bedrock::AbstractServiceFactory { +class BaseComponent : public bedrock::AbstractComponent { - public: - - BaseServiceFactory() = default; - - virtual ~BaseServiceFactory() = default; - - void* registerProvider(const bedrock::FactoryArgs& args) override { - return new TestProvider(args); - } - - void deregisterProvider(void* provider) override { - delete static_cast(provider); - } - - std::string getProviderConfig(void* provider) override { - return static_cast(provider)->config; - } + std::unique_ptr m_provider; - void* initClient(const bedrock::FactoryArgs& args) override { - return new TestClient(args); - } - - void finalizeClient(void* client) override { - delete static_cast(client); - } + public: - std::string getClientConfig(void* client) override { - return static_cast(client)->config; - } + BaseComponent(const bedrock::ComponentArgs& args) + : m_provider{std::make_unique(args)} {} - void* createProviderHandle(void* client, hg_addr_t address, uint16_t provider_id) override { - return new TestProviderHandle(client, address, provider_id); - } + virtual ~BaseComponent() = default; - void destroyProviderHandle(void* providerHandle) override { - delete static_cast(providerHandle); + void* getHandle() override { + return static_cast(m_provider.get()); } - std::vector getProviderDependencies(const char*) override { - return {}; - } + static std::shared_ptr + Register(const bedrock::ComponentArgs& args) { + return std::make_shared(args); + } - std::vector getClientDependencies(const char*) override { - return {}; - } + static std::vector + GetDependencies(const bedrock::ComponentArgs& args) { + return std::vector{}; + } }; diff --git a/tests/modules/Helpers.hpp b/tests/modules/Helpers.hpp index d9878ab..fcf429e 100644 --- a/tests/modules/Helpers.hpp +++ b/tests/modules/Helpers.hpp @@ -3,74 +3,29 @@ #include #include -#include +#include struct TestProvider { - std::string name; - margo_instance_id mid; - uint16_t provider_id; - ABT_pool pool; - std::string config; - std::unordered_map> dependencies; + std::string name; + thallium::engine engine; + uint16_t provider_id; + std::string config; + std::unordered_map< + std::string, std::vector> dependencies; - TestProvider(const bedrock::FactoryArgs& args) + TestProvider(const bedrock::ComponentArgs& args) : name(args.name) - , mid(args.mid) + , engine(args.engine) , provider_id(args.provider_id) - , pool(args.pool) , config(args.config) { for(const auto& dep : args.dependencies) { - for(const auto& a : dep.second.dependencies) { - dependencies[dep.first].push_back(a->getHandle()); + for(const auto& a : dep.second) { + dependencies[dep.first].push_back(a->getName()); } } } }; -struct TestClient { - - std::string name; - margo_instance_id mid; - uint16_t provider_id; - ABT_pool pool; - std::string config; - std::unordered_map> dependencies; - - TestClient(const bedrock::FactoryArgs& args) - : name(args.name) - , mid(args.mid) - , provider_id(args.provider_id) - , pool(args.pool) - , config(args.config) - { - for(const auto& dep : args.dependencies) { - for(const auto& a : dep.second.dependencies) { - dependencies[dep.first].push_back(a->getHandle()); - } - } - } -}; - -struct TestProviderHandle { - - TestClient* client; - hg_addr_t addr = HG_ADDR_NULL; - uint16_t provider_id; - - TestProviderHandle(void* c, hg_addr_t a, uint16_t pr_id) - : client(static_cast(c)) - , provider_id(pr_id) - { - margo_addr_dup(client->mid, a, &addr); - } - - ~TestProviderHandle() - { - margo_addr_free(client->mid, addr); - } - -}; - #endif diff --git a/tests/modules/ModuleA.cpp b/tests/modules/ModuleA.cpp index 89450ec..ee3ab20 100644 --- a/tests/modules/ModuleA.cpp +++ b/tests/modules/ModuleA.cpp @@ -1,7 +1,11 @@ #include "BaseModule.hpp" -class ModuleAServiceFactory : public BaseServiceFactory { +class ComponentA : public BaseComponent { + public: + + using BaseComponent::Register; + using BaseComponent::GetDependencies; }; -BEDROCK_REGISTER_MODULE_FACTORY(module_a, ModuleAServiceFactory) +BEDROCK_REGISTER_COMPONENT_TYPE(module_a, ComponentA) diff --git a/tests/modules/ModuleB.cpp b/tests/modules/ModuleB.cpp index d3af54d..df91a8b 100644 --- a/tests/modules/ModuleB.cpp +++ b/tests/modules/ModuleB.cpp @@ -1,7 +1,11 @@ #include "BaseModule.hpp" -class ModuleBServiceFactory : public BaseServiceFactory { +class ComponentB : public BaseComponent { + public: + + using BaseComponent::Register; + using BaseComponent::GetDependencies; }; -BEDROCK_REGISTER_MODULE_FACTORY(module_b, ModuleBServiceFactory) +BEDROCK_REGISTER_COMPONENT_TYPE(module_b, ComponentB) diff --git a/tests/modules/ModuleC.cpp b/tests/modules/ModuleC.cpp index 0796604..f399adf 100644 --- a/tests/modules/ModuleC.cpp +++ b/tests/modules/ModuleC.cpp @@ -1,9 +1,37 @@ -#include "BaseModule.hpp" +#include "Helpers.hpp" #include -using json = nlohmann::json; +class ComponentC : public bedrock::AbstractComponent { -class ModuleCServiceFactory : public BaseServiceFactory { + using json = nlohmann::json; + + std::unique_ptr m_provider; + + public: + + ComponentC(const bedrock::ComponentArgs& args) + : m_provider{std::make_unique(args)} {} + + void* getHandle() override { + return static_cast(m_provider.get()); + } + + static std::shared_ptr + Register(const bedrock::ComponentArgs& args) { + return std::make_shared(args); + } + + static std::vector + GetDependencies(const bedrock::ComponentArgs& args) { + auto config = json::parse(args.config); + std::vector dependencies; + if(!config.contains("expected_provider_dependencies")) + return dependencies; + auto& expected_dependencies = config["expected_provider_dependencies"]; + return extractDependencies(expected_dependencies); + } + + private: static inline std::vector extractDependencies( const json& expected_dependencies) { @@ -14,48 +42,17 @@ class ModuleCServiceFactory : public BaseServiceFactory { if(!dep.is_object()) continue; if(!dep.contains("name") || !dep.contains("type")) continue; - int32_t flags = 0; - auto name = dep["name"].get(); - auto type = dep["type"].get(); - auto kind = dep.value("kind", std::string{""}); - if(kind == "client") { - flags |= BEDROCK_KIND_CLIENT; - } - if(kind == "provider") { - flags |= BEDROCK_KIND_PROVIDER; - } - if(kind == "provider_handle") { - flags |= BEDROCK_KIND_PROVIDER_HANDLE; - } - if(dep.value("is_required", false)) { - flags |= BEDROCK_REQUIRED; - } - if(dep.value("is_array", false)) { - flags |= BEDROCK_ARRAY; - } - dependencies.push_back(bedrock::Dependency{name, type, flags}); + bedrock::Dependency the_dep; + the_dep.name = dep["name"].get(); + the_dep.type = dep["type"].get(); + the_dep.is_array = dep.value("is_array", false); + the_dep.is_required = dep.value("is_required", false); + the_dep.is_updatable = dep.value("is_updatable", false); + dependencies.push_back(the_dep); } return dependencies; } - std::vector getProviderDependencies(const char* cfg) override { - auto config = json::parse(cfg); - std::vector dependencies; - if(!config.contains("expected_provider_dependencies")) - return dependencies; - auto& expected_dependencies = config["expected_provider_dependencies"]; - return extractDependencies(expected_dependencies); - } - - std::vector getClientDependencies(const char* cfg) override { - auto config = json::parse(cfg); - std::vector dependencies; - if(!config.contains("expected_client_dependencies")) - return dependencies; - auto& expected_dependencies = config["expected_client_dependencies"]; - return extractDependencies(expected_dependencies); - } - }; -BEDROCK_REGISTER_MODULE_FACTORY(module_c, ModuleCServiceFactory) +BEDROCK_REGISTER_COMPONENT_TYPE(module_c, ComponentC) From 7aa92df47e379f88ac89beeea0eed31e23df8b24 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Thu, 5 Sep 2024 16:05:25 +0100 Subject: [PATCH 07/10] new way of specifying provider spaces --- python/mochi/bedrock/config_space.py | 19 +++++++++ python/mochi/bedrock/spec.py | 48 ++++++++++++++++------- python/mochi/bedrock/test_config_space.py | 31 +++++++++++++-- 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/python/mochi/bedrock/config_space.py b/python/mochi/bedrock/config_space.py index 1de4afb..a006cd7 100644 --- a/python/mochi/bedrock/config_space.py +++ b/python/mochi/bedrock/config_space.py @@ -153,6 +153,25 @@ def convert_condition_tuples(child_name, conditions: list[tuple[type,str,Any]]): return self._inner +class PrefixedConfigSpaceWrapper: + + def __init__(self, configuration_space: ConfigurationSpace, prefix: str): + self.prefix = prefix + self.cs = configuration_space + + def add(self, arg): + if isinstance(arg, Hyperparameter): + arg.name = self.prefix + arg.name + if isinstance(arg, list): + for a in args: + self.add(a) + else: + self.cs.add(arg) + + def __getattr__(self, key): + return getattr(self.cs, key) + + def CategoricalOrConst(name: str, items: Sequence[Any]|Any, *, default: Any|None = None, weights: Sequence[float]|None = None, ordered: bool = False, meta: dict|None = None): diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index c800121..dc1abc1 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -14,6 +14,7 @@ import json import attr +from abc import ABC, abstractmethod from attr import Factory from attr.validators import instance_of, in_ from typing import List, NoReturn, Union, Optional, Sequence, Any, Callable, Mapping @@ -1369,9 +1370,25 @@ def from_config(*, config: Config, prefix: str = '', **kwargs) -> 'MargoSpec': **extra) -#ProviderConfigSpaceMaker = Callable[[CS], CS] -#ProviderConfigResolver = Callable[[CS], None] -#ProviderDependencyResolver = Callable[[Config, str], dict] +class ProviderConfigSpaceBuilder(ABC): + + @abstractmethod + def set_provider_hyperparameters(self, configuration_space: CS) -> None: + """ + This method can add hyperparameters, conditions, and forbidden clauses + to the provided configuration_space. These hyperparameters will internally + be added to the configuration space with a prefix. + """ + pass + + @abstractmethod + def resolve_to_provider_spec( + self, name: str, provider_id: int, config: Config, prefix: str) -> 'ProviderSpec': + """ + This method should convert a Configuration object into a ProviderSpec, + by extracting the configuration and dependencies from the sampled parameters. + """ + pass @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) @@ -1698,6 +1715,7 @@ def space(*, provider_space_factories: list[dict] = [], """ from .config_space import ( ConfigurationSpace, + PrefixedConfigSpaceWrapper, GreaterThanCondition, ForbiddenInClause, ForbiddenAndConjunction, @@ -1719,26 +1737,27 @@ def space(*, provider_space_factories: list[dict] = [], # for each family of providers... for provider_group in provider_space_factories: family = provider_group['family'] - provider_cs = provider_group['space'] + builder = provider_group['builder'] count = provider_group.get('count', 1) default_count = count if isinstance(count, int) else count[0] # number of providers hp_num_providers = IntegerOrConst(f'providers.{family}.num_providers', count, default=default_count) cs.add(hp_num_providers) - # add each provider's sub-space + cs.add(Constant(f'providers.{family}.builder', builder)) + # build each provider's sub-space for i in range(0, hp_num_providers.upper): - space_prefix = f'providers.{family}[{i}]' - cs.add_configuration_space( - prefix=space_prefix, delimiter='.', - configuration_space=provider_cs) + space_prefix = f'providers.{family}[{i}].' + builder.set_provider_hyperparameters( + configuration_space=PrefixedConfigSpaceWrapper(cs, space_prefix)) # add conditions on all the hyperparameters of the sub-space, # they exist only if i < num_providers. if i <= hp_num_providers.lower: continue - for param in provider_cs: - param_key = f'{space_prefix}.{param}' - cs.add(GreaterThanCondition(cs[param_key], hp_num_providers, i)) + for param_name in cs: + if not param_name.startswith(space_prefix): + continue + cs.add(GreaterThanCondition(cs[param_name], hp_num_providers, i)) return cs @staticmethod @@ -1756,10 +1775,11 @@ def from_config(*, config: Config, prefix: str = '', **kwargs) -> 'ProcSpec': provider_specs = [] for family in families: num_providers = int(config[f'{prefix}providers.{family}.num_providers']) + builder = config[f'{prefix}providers.{family}.builder'] for i in range(num_providers): provider_specs.append( - ProviderSpec.from_config( - name=f'{family}_{i}', #pools=margo_spec.argobots.pools, + builder.resolve_to_provider_spec( + name=f'{family}_{i}', provider_id=current_provider_id, config=config, prefix=f'{prefix}providers.{family}[{i}].')) current_provider_id += 1 diff --git a/python/mochi/bedrock/test_config_space.py b/python/mochi/bedrock/test_config_space.py index 4be7c0e..17e3c0f 100644 --- a/python/mochi/bedrock/test_config_space.py +++ b/python/mochi/bedrock/test_config_space.py @@ -110,6 +110,7 @@ def test_proc_with_providers(self): max_num_pools = 3 + """ provider_config_cs = ConfigurationSpace() provider_config_cs.add(Integer("x", (0,9))) provider_config_cs.add(Integer("y", (1,42))) @@ -135,14 +136,38 @@ def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: "count": (1,3) } ] + """ + class MyProviderSpaceBuilder(ProviderConfigSpaceBuilder): + + def set_provider_hyperparameters(self, configuration_space: CS) -> None: + configuration_space.add(Integer("x", (0,9))) + configuration_space.add(Integer("y", (1,42))) + + def resolve_to_provider_spec( + self, name: str, provider_id: int, config: Config, prefix: str) -> ProviderSpec: + cfg = { + "x" : int(config[prefix + "x"]), + "y" : int(config[prefix + "y"]) + } + return ProviderSpec( + name=name, type="yokan", provider_id=provider_id, + tags=["tag1", "tag2"], config=cfg, dependencies={}) + + provider_space_factories = [ + { + "family": "databases", + "builder": MyProviderSpaceBuilder(), + "count": (1,3) + } + ] space = ProcSpec.space(num_pools=(1, max_num_pools), num_xstreams=(2, 5), provider_space_factories=provider_space_factories).freeze() - #print(space) + print(space) config = space.sample_configuration() - #print(config) + print(config) spec = ProcSpec.from_config(address='na+sm', config=config) - #print(spec.to_json(indent=4)) + print(spec.to_json(indent=4)) def test_service_config_space(self): From ffa5e03e9e871f5a3b2d28928499178ca602dddf Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Thu, 5 Sep 2024 16:28:27 +0100 Subject: [PATCH 08/10] implemented new way of providing a provider space --- python/mochi/bedrock/config_space.py | 11 +- python/mochi/bedrock/spec.py | 65 +--------- python/mochi/bedrock/test_config_space.py | 150 +++++++++------------- 3 files changed, 74 insertions(+), 152 deletions(-) diff --git a/python/mochi/bedrock/config_space.py b/python/mochi/bedrock/config_space.py index a006cd7..5a651da 100644 --- a/python/mochi/bedrock/config_space.py +++ b/python/mochi/bedrock/config_space.py @@ -163,7 +163,7 @@ def add(self, arg): if isinstance(arg, Hyperparameter): arg.name = self.prefix + arg.name if isinstance(arg, list): - for a in args: + for a in arg: self.add(a) else: self.cs.add(arg) @@ -171,6 +171,15 @@ def add(self, arg): def __getattr__(self, key): return getattr(self.cs, key) + def __iter__(self): + return self.cs.__iter__() + + def __getitem__(self, name): + return self.cs[name] + + def __contains__(self, name): + return name in self.cs + def CategoricalOrConst(name: str, items: Sequence[Any]|Any, *, default: Any|None = None, weights: Sequence[float]|None = None, diff --git a/python/mochi/bedrock/spec.py b/python/mochi/bedrock/spec.py index dc1abc1..b531e41 100644 --- a/python/mochi/bedrock/spec.py +++ b/python/mochi/bedrock/spec.py @@ -1383,7 +1383,8 @@ def set_provider_hyperparameters(self, configuration_space: CS) -> None: @abstractmethod def resolve_to_provider_spec( - self, name: str, provider_id: int, config: Config, prefix: str) -> 'ProviderSpec': + self, name: str, provider_id: int, + config: Config, prefix: str) -> 'ProviderSpec': """ This method should convert a Configuration object into a ProviderSpec, by extracting the configuration and dependencies from the sampled parameters. @@ -1467,68 +1468,6 @@ def from_json(json_string: str) -> 'ProviderSpec': """ return ProviderSpec.from_dict(json.loads(json_string)) - @staticmethod - def space(*, type: str, tags: list[str] = [], - provider_config_space: Optional[CS] = None, - provider_config_resolver: Callable[[Config, str], dict]|None = None, - dependency_config_space: Optional[CS] = None, - dependency_resolver: Callable[[Config, str], dict]|None = None) -> CS: - """ - Create a ConfigurationSpace for a ProviderSpec. - - - type: type of provider. - - tags: list of tags the provider will use. - - provider_config_space: a ConfigurationSpace for the "config" field of the provider. - - provider_config_resolver: a function (or callable) taking a Configuration and a prefix - and returning the provider's "config" field (dict) from the Configuration. - - dependency_config_space: a ConfigurationSpace for the "dependencies" field of the provider. - - dependency_resolver: a function (or callable) taking a Configuration and a prefix - and returning the provider's "dependencies" field (dict) from the Configuration. - """ - from .config_space import ConfigurationSpace, FloatOrConst, Categorical, Constant - cs = ConfigurationSpace() - cs.add(Constant('type', type)) - cs.add(Constant('tags', tags)) - - if provider_config_space is not None: - cs.add_configuration_space( - prefix='config', delimiter='.', - configuration_space=provider_config_space) - cs.add(Constant('config_resolver', provider_config_resolver)) - if dependency_config_space is not None: - cs.add_configuration_space( - prefix='dependencies', delimiter='.', - configuration_space=dependency_config_space) - cs.add(Constant('dependency_resolver', dependency_resolver)) - return cs - - @staticmethod - def from_config(*, name: str, provider_id: int, - config: Config, prefix: str = '') -> 'ProviderSpec': - """ - Create a ProviderSpec from a given Configuration object. - - This function must be also given the name and provider Id to give the provider, - as well as the list of pools of the underlying ProcSpec. - """ - from .config_space import Configuration - type = config[f'{prefix}type'] - tags = config[f'{prefix}tags'] - provider_config_resolver = config[f'{prefix}config_resolver'] - dependency_resolver = config[f'{prefix}dependency_resolver'] - if provider_config_resolver is None: - provider_config = {} - else: - provider_config = provider_config_resolver(config, f'{prefix}config.') - if dependency_resolver is None: - provider_dependencies = {} - else: - provider_dependencies = dependency_resolver(config, f'{prefix}dependencies.') - return ProviderSpec( - name=name, type=type, provider_id=provider_id, - config=provider_config, tags=tags, - dependencies=provider_dependencies) - @attr.s(auto_attribs=True, on_setattr=_check_validators, kw_only=True) class BedrockSpec: diff --git a/python/mochi/bedrock/test_config_space.py b/python/mochi/bedrock/test_config_space.py index 17e3c0f..9165f0d 100644 --- a/python/mochi/bedrock/test_config_space.py +++ b/python/mochi/bedrock/test_config_space.py @@ -1,5 +1,27 @@ import unittest from mochi.bedrock.spec import * +from .config_space import ConfigurationSpace, Integer, CategoricalChoice + +class MyDatabaseSpaceBuilder(ProviderConfigSpaceBuilder): + + def set_provider_hyperparameters(self, configuration_space: CS) -> None: + configuration_space.add(Integer("x", (0,9))) + configuration_space.add(Integer("y", (1,42))) + # add a pool dependency + num_pools = configuration_space["margo.argobots.num_pools"] + configuration_space.add(CategoricalChoice("pool", num_options=num_pools)) + + def resolve_to_provider_spec( + self, name: str, provider_id: int, config: Config, prefix: str) -> ProviderSpec: + cfg = { + "x" : int(config[prefix + "x"]), + "y" : int(config[prefix + "y"]) + } + dep = { + "pool" : int(config[prefix + "pool"]) + } + return ProviderSpec(name=name, type="yokan", provider_id=provider_id, + tags=["tag1", "tag2"], config=cfg, dependencies=dep) class TestConfigSpace(unittest.TestCase): @@ -69,110 +91,62 @@ def test_proc_config_space(self): spec = ProcSpec.from_config(config=config, address='na+sm') #print(spec.to_json(indent=4)) - def test_provider_config_space(self): - from .config_space import ConfigurationSpace, Integer - # pools to select from - # pools = [PoolSpec(name=f'pool_{i}') for i in range(5)] - - # config space for the provider - config_cs = ConfigurationSpace() - config_cs.add(Integer("x", (0,9))) - config_cs.add(Integer("y", (1,42))) - - # function to resolve the configuration - def resolve_provider_config(config: 'Configuration', prefix: str) -> dict: - x = config[f'{prefix}x'] - y = config[f'{prefix}y'] - return {'x':x, 'y':y} - - # function to resolve the dependencies - def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: - return {'abc': 'def'} - - space = ProviderSpec.space( - type='yokan', - tags=['tag1', 'tag2'], - provider_config_space=config_cs, - provider_config_resolver=resolve_provider_config, - dependency_resolver=resolve_provider_dependencies).freeze() - #print(space) - - config = space.sample_configuration() - #print(config) - - spec = ProviderSpec.from_config( - name='my_yokan_provider', provider_id=1, - config=config) - #print(spec.to_json(indent=4)) - def test_proc_with_providers(self): - from .config_space import ConfigurationSpace, Integer - - max_num_pools = 3 - - """ - provider_config_cs = ConfigurationSpace() - provider_config_cs.add(Integer("x", (0,9))) - provider_config_cs.add(Integer("y", (1,42))) - - def resolve_provider_config(config: 'Configuration', prefix: str) -> dict: - x = config[f'{prefix}x'] - y = config[f'{prefix}y'] - return {'x':x, 'y':y} - - def resolve_provider_dependencies(config: 'Configuration', prefix: str) -> dict: - return {'abc': 'def'} - provider_space_factories = [ { "family": "databases", - "space": ProviderSpec.space( - type='yokan', - #max_num_pools=max_num_pools, - tags=['tag1', 'tag2'], - provider_config_space=provider_config_cs, - provider_config_resolver=resolve_provider_config, - dependency_resolver=resolve_provider_dependencies), + "builder": MyDatabaseSpaceBuilder(), "count": (1,3) } ] - """ + space = ProcSpec.space(num_pools=(1, 3), num_xstreams=(2, 5), + provider_space_factories=provider_space_factories).freeze() + #print(space) + config = space.sample_configuration() + #print(config) + spec = ProcSpec.from_config(address='na+sm', config=config) + #print(spec.to_json(indent=4)) - class MyProviderSpaceBuilder(ProviderConfigSpaceBuilder): + def test_service_config_space(self): - def set_provider_hyperparameters(self, configuration_space: CS) -> None: - configuration_space.add(Integer("x", (0,9))) - configuration_space.add(Integer("y", (1,42))) + proc_type_a = ProcSpec.space(num_pools=2, num_xstreams=3) + proc_type_b = ProcSpec.space(num_pools=1, num_xstreams=2) - def resolve_to_provider_spec( - self, name: str, provider_id: int, config: Config, prefix: str) -> ProviderSpec: - cfg = { - "x" : int(config[prefix + "x"]), - "y" : int(config[prefix + "y"]) + space = ServiceSpec.space( + process_space_factories=[ + { + 'family': 'proc_type_a', + 'space': proc_type_a, + 'count': 2 + }, + { + 'family': 'proc_type_b', + 'space': proc_type_b, + 'count': 2 } - return ProviderSpec( - name=name, type="yokan", provider_id=provider_id, - tags=["tag1", "tag2"], config=cfg, dependencies={}) + ]).freeze() + #print(space) + + config = space.sample_configuration() + #print(config) + + spec = ServiceSpec.from_config(address='na+sm', config=config) + #print(spec.to_json(indent=4)) + + def test_service_config_space_with_providers(self): provider_space_factories = [ { "family": "databases", - "builder": MyProviderSpaceBuilder(), + "builder": MyDatabaseSpaceBuilder(), "count": (1,3) } ] - space = ProcSpec.space(num_pools=(1, max_num_pools), num_xstreams=(2, 5), - provider_space_factories=provider_space_factories).freeze() - print(space) - config = space.sample_configuration() - print(config) - spec = ProcSpec.from_config(address='na+sm', config=config) - print(spec.to_json(indent=4)) - def test_service_config_space(self): - - proc_type_a = ProcSpec.space(num_pools=2, num_xstreams=3) - proc_type_b = ProcSpec.space(num_pools=1, num_xstreams=2) + proc_type_a = ProcSpec.space(num_pools=3, num_xstreams=3, + provider_space_factories=provider_space_factories) + proc_type_b = ProcSpec.space(num_pools=2, num_xstreams=2, + provider_space_factories=provider_space_factories) space = ServiceSpec.space( process_space_factories=[ @@ -187,13 +161,13 @@ def test_service_config_space(self): 'count': 2 } ]).freeze() - #print(space) + print(space) config = space.sample_configuration() - #print(config) + print(config) spec = ServiceSpec.from_config(address='na+sm', config=config) - #print(spec.to_json(indent=4)) + print(spec.to_json(indent=4)) if __name__ == '__main__': unittest.main() From 6fab3be38fcaf63ced4ee32677f4b248321c0c49 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Thu, 5 Sep 2024 16:56:13 +0100 Subject: [PATCH 09/10] added a way to reference pools and xstream by index in dependencies --- include/bedrock/DependencyFinder.hpp | 15 +++++++++ python/mochi/bedrock/test_config_space.py | 6 ++-- python/mochi/bedrock/test_dependencies.py | 40 +++++++++++++++++++++++ src/DependencyFinder.cpp | 30 +++++++++++++++++ src/ProviderManager.cpp | 31 +++++++++++------- src/ProviderManagerImpl.hpp | 9 ----- 6 files changed, 107 insertions(+), 24 deletions(-) diff --git a/include/bedrock/DependencyFinder.hpp b/include/bedrock/DependencyFinder.hpp index 147de07..8cd0b6e 100644 --- a/include/bedrock/DependencyFinder.hpp +++ b/include/bedrock/DependencyFinder.hpp @@ -104,6 +104,21 @@ class DependencyFinder { const std::string& spec, std::string* resolved) const; + /** + * @brief Find a dependency by an "index" value. The dependency + * should be a pool or an xstream + * + * @param [in] type Type of dependency. + * @param [in] index Index of the dependency. + * @param [out] resolved Resolved specification. + * + * @return handle to dependency + */ + std::shared_ptr + find(const std::string& type, + size_t index, + std::string* resolved) const; + /** * @brief Find a local provider based on a type and provider id. * Throws an exception if not found. diff --git a/python/mochi/bedrock/test_config_space.py b/python/mochi/bedrock/test_config_space.py index 9165f0d..acf27ec 100644 --- a/python/mochi/bedrock/test_config_space.py +++ b/python/mochi/bedrock/test_config_space.py @@ -161,13 +161,13 @@ def test_service_config_space_with_providers(self): 'count': 2 } ]).freeze() - print(space) + #print(space) config = space.sample_configuration() - print(config) + #print(config) spec = ServiceSpec.from_config(address='na+sm', config=config) - print(spec.to_json(indent=4)) + #print(spec.to_json(indent=4)) if __name__ == '__main__': unittest.main() diff --git a/python/mochi/bedrock/test_dependencies.py b/python/mochi/bedrock/test_dependencies.py index 5f2780b..aea7ddf 100644 --- a/python/mochi/bedrock/test_dependencies.py +++ b/python/mochi/bedrock/test_dependencies.py @@ -124,6 +124,26 @@ def test_dependency_on_pool(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) + def test_dependency_on_pool_by_index(self): + providers = self.server.providers + self.assertEqual(len(providers), 2) + + # Try creating a provider without the required dependency + provider_params = self.make_provider_params([ + {"name": "dep1", "type": "pool", "is_required": True}]) + with self.assertRaises(mbs.BedrockException): + providers.create(**provider_params) + + # Try creating a provider with a wrong dependency + provider_params["dependencies"] = {"dep1": 123} + with self.assertRaises(mbs.BedrockException): + providers.create(**provider_params) + + # Try creating a provider with the required dependency + provider_params["dependencies"] = {"dep1": 1} + providers.create(**provider_params) + self.assertEqual(len(providers), 3) + def test_dependency_on_xstream(self): providers = self.server.providers self.assertEqual(len(providers), 2) @@ -144,6 +164,26 @@ def test_dependency_on_xstream(self): providers.create(**provider_params) self.assertEqual(len(providers), 3) + def test_dependency_on_xstream_by_index(self): + providers = self.server.providers + self.assertEqual(len(providers), 2) + + # Try creating a provider without the required dependency + provider_params = self.make_provider_params([ + {"name": "dep1", "type": "xstream", "is_required": True}]) + with self.assertRaises(mbs.BedrockException): + providers.create(**provider_params) + + # Try creating a provider with the wrong dependency + provider_params["dependencies"] = {"dep1": 123} + with self.assertRaises(mbs.BedrockException): + providers.create(**provider_params) + + # Try creating a provider with the required dependency + provider_params["dependencies"] = {"dep1": 1} + providers.create(**provider_params) + self.assertEqual(len(providers), 3) + def test_dependency_on_provider(self): providers = self.server.providers self.assertEqual(len(providers), 2) diff --git a/src/DependencyFinder.cpp b/src/DependencyFinder.cpp index 93942e2..243a650 100644 --- a/src/DependencyFinder.cpp +++ b/src/DependencyFinder.cpp @@ -126,6 +126,36 @@ std::shared_ptr DependencyFinder::find( return nullptr; } +std::shared_ptr DependencyFinder::find( + const std::string& type, + size_t index, + std::string* resolved) const { + spdlog::trace("DependencyFinder search dependency of type {} at index {}", type, index); + + if (type == "pool") { // Argobots pool + + auto pool = MargoManager(self->m_margo_context).getPool(index); + if (!pool) { + throw Exception("Could not find pool at index \"{}\"", index); + } + if (resolved) { *resolved = pool->getName(); } + return pool; + + } else if (type == "xstream") { // Argobots xstream + + auto xstream = MargoManager(self->m_margo_context).getXstream(index); + if (!xstream) { + throw Exception("Could not find xstream at index \"{}\"", index); + } + if (resolved) { *resolved = xstream->getName(); } + return xstream; + + } else { + throw Exception("Only pools and xstream can be referenced by index"); + } + return nullptr; +} + std::shared_ptr DependencyFinder::findProvider(const std::string& type, uint16_t provider_id) const { diff --git a/src/ProviderManager.cpp b/src/ProviderManager.cpp index 3059eb4..98801ac 100644 --- a/src/ProviderManager.cpp +++ b/src/ProviderManager.cpp @@ -119,7 +119,15 @@ ProviderManager::addProviderFromJSON(const json& description) { "additionalProperties": { "anyOf": [ {"type": "string"}, - {"type": "array", "items": {"type": "string"}} + {"type": "integer"}, + {"type": "array", + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"} + ] + } + } ] } }, @@ -148,21 +156,19 @@ ProviderManager::addProviderFromJSON(const json& description) { spdlog::trace("Resolving dependency {}", dependency.name); if (deps_from_config.contains(dependency.name)) { auto dep_config = deps_from_config[dependency.name]; - if (!(dependency.is_array)) { // dependency should be a string + if (!(dependency.is_array)) { // dependency should be a string or an integer if (dep_config.is_array() && dep_config.size() == 1) { // an array of length 1 can be converted into a single string dep_config = dep_config[0]; } - if (!dep_config.is_string()) { - throw BEDROCK_DETAILED_EXCEPTION( - "Dependency \"{}\" should be a string", dependency.name); - } - auto dep_handle = dependencyFinder.find( - dependency.type, dep_config.get(), nullptr); + auto dep_handle = dep_config.is_string() ? + dependencyFinder.find(dependency.type, dep_config.get(), nullptr) + : dependencyFinder.find(dependency.type, dep_config.get(), nullptr); resolved_dependency_map[dependency.name].push_back(dep_handle); } else { // dependency is an array - if (dep_config.is_string()) { + + if (dep_config.is_string() || dep_config.is_number_unsigned()) { // a single string can be converted into an array of size 1 auto tmp_array = json::array(); tmp_array.push_back(dep_config); @@ -173,10 +179,11 @@ ProviderManager::addProviderFromJSON(const json& description) { "Dependency \"{}\" should be an array", dependency.name); } - std::vector deps; for (const auto& elem : dep_config) { - auto dep_handle = dependencyFinder.find( - dependency.type, elem.get(), nullptr); + auto dep_handle = elem.is_string() ? + dependencyFinder.find(dependency.type, elem.get(), nullptr) + : dependencyFinder.find(dependency.type, elem.get(), nullptr); + resolved_dependency_map[dependency.name].push_back(dep_handle); } } diff --git a/src/ProviderManagerImpl.hpp b/src/ProviderManagerImpl.hpp index e33b3dc..7319a0a 100644 --- a/src/ProviderManagerImpl.hpp +++ b/src/ProviderManagerImpl.hpp @@ -47,15 +47,6 @@ class LocalProvider : public ProviderDependency { , resolved_dependencies(std::move(res_deps)) , tags(std::move(_tags)) { - std::cerr << "Created LocalProvider with name " << getName() - << ", type " << getType() << ", provider id " << provider_id - << ", and the following dependency map:" << std::endl; - for(auto& p : resolved_dependencies) { - std::cerr << p.first << ": " << std::endl; - for(auto d : p.second) { - std::cerr << " " << d->getName() << std::endl; - } - } } json makeConfig() const { From 8a989ecd9238d041983a21b30741f3f39c72ac73 Mon Sep 17 00:00:00 2001 From: Matthieu Dorier Date: Tue, 17 Sep 2024 16:29:52 +0100 Subject: [PATCH 10/10] added build-develop.yml --- .github/workflows/build-develop.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/build-develop.yml diff --git a/.github/workflows/build-develop.yml b/.github/workflows/build-develop.yml new file mode 100644 index 0000000..ead9353 --- /dev/null +++ b/.github/workflows/build-develop.yml @@ -0,0 +1,16 @@ +name: Build the develop version using Spack + +on: + workflow_dispatch: {} + schedule: + - cron: "0 0 * * *" + +jobs: + build: + runs-on: ubuntu-22.04 + name: Build the main version of the package + steps: + - uses: actions/checkout@v4 + - uses: mochi-hpc/mochi-test-build-action@v1 + with: + package-version: "@develop"