diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 7cac3421c..41ebb3dd6 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -142,6 +142,7 @@ file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/cortex_openapi.h" add_executable(${TARGET_NAME} main.cc ${CMAKE_CURRENT_SOURCE_DIR}/utils/cpuid/cpu_info.cc ${CMAKE_CURRENT_SOURCE_DIR}/utils/file_logger.cc + ${CMAKE_CURRENT_SOURCE_DIR}/utils/dylib_path_manager.cc ${CMAKE_CURRENT_SOURCE_DIR}/extensions/remote-engine/remote_engine.cc ${CMAKE_CURRENT_SOURCE_DIR}/extensions/remote-engine/openai_engine.cc ${CMAKE_CURRENT_SOURCE_DIR}/extensions/remote-engine/anthropic_engine.cc diff --git a/engine/cli/CMakeLists.txt b/engine/cli/CMakeLists.txt index 51382dc13..237596f21 100644 --- a/engine/cli/CMakeLists.txt +++ b/engine/cli/CMakeLists.txt @@ -75,6 +75,7 @@ find_package(lfreist-hwinfo CONFIG REQUIRED) add_executable(${TARGET_NAME} main.cc ${CMAKE_CURRENT_SOURCE_DIR}/../utils/cpuid/cpu_info.cc ${CMAKE_CURRENT_SOURCE_DIR}/../utils/file_logger.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../utils/dylib_path_manager.cc ${CMAKE_CURRENT_SOURCE_DIR}/command_line_parser.cc ${CMAKE_CURRENT_SOURCE_DIR}/../services/config_service.cc ${CMAKE_CURRENT_SOURCE_DIR}/../services/download_service.cc diff --git a/engine/cli/command_line_parser.cc b/engine/cli/command_line_parser.cc index 624ccd3dd..825780895 100644 --- a/engine/cli/command_line_parser.cc +++ b/engine/cli/command_line_parser.cc @@ -48,8 +48,11 @@ constexpr const auto kSubcommands = "Subcommands"; CommandLineParser::CommandLineParser() : app_("\nCortex.cpp CLI\n"), download_service_{std::make_shared()}, - model_service_{ModelService(download_service_)}, - engine_service_{EngineService(download_service_)} {} + dylib_path_manager_{std::make_shared()}, + engine_service_{std::make_shared(download_service_, + dylib_path_manager_)} { + supported_engines_ = engine_service_->GetSupportedEngineNames().value(); +} bool CommandLineParser::SetupCommand(int argc, char** argv) { app_.usage("Usage:\n" + commands::GetCortexBinary() + @@ -60,8 +63,6 @@ bool CommandLineParser::SetupCommand(int argc, char** argv) { SetupCommonCommands(); - SetupInferenceCommands(); - SetupModelCommands(); SetupEngineCommands(); @@ -176,17 +177,11 @@ void CommandLineParser::SetupCommonCommands() { return; commands::RunCmd rc(cml_data_.config.apiServerHost, std::stoi(cml_data_.config.apiServerPort), - cml_data_.model_id, download_service_); + cml_data_.model_id, engine_service_); rc.Exec(cml_data_.run_detach, run_settings_); }); } -void CommandLineParser::SetupInferenceCommands() { - // auto embeddings_cmd = app_.add_subcommand( - // "embeddings", "Creates an embedding vector representing the input text"); - // embeddings_cmd->group(kInferenceGroup); -} - void CommandLineParser::SetupModelCommands() { // Models group commands auto models_cmd = @@ -476,7 +471,7 @@ void CommandLineParser::SetupEngineCommands() { list_engines_cmd->callback([this]() { if (std::exchange(executed_, true)) return; - commands::EngineListCmd command; + auto command = commands::EngineListCmd(engine_service_); command.Exec(cml_data_.config.apiServerHost, std::stoi(cml_data_.config.apiServerPort)); }); @@ -493,9 +488,9 @@ void CommandLineParser::SetupEngineCommands() { CLI_LOG(install_cmd->help()); } }); - for (const auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineInstall(install_cmd, engine_name, cml_data_.engine_version, + + for (const auto& engine : supported_engines_) { + EngineInstall(install_cmd, engine, cml_data_.engine_version, cml_data_.engine_src); } @@ -512,9 +507,8 @@ void CommandLineParser::SetupEngineCommands() { } }); uninstall_cmd->group(kSubcommands); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineUninstall(uninstall_cmd, engine_name); + for (const auto& engine : supported_engines_) { + EngineUninstall(uninstall_cmd, engine); } auto engine_upd_cmd = engines_cmd->add_subcommand("update", "Update engine"); @@ -529,9 +523,8 @@ void CommandLineParser::SetupEngineCommands() { } }); engine_upd_cmd->group(kSubcommands); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineUpdate(engine_upd_cmd, engine_name); + for (const auto& engine : supported_engines_) { + EngineUpdate(engine_upd_cmd, engine); } auto engine_use_cmd = @@ -547,9 +540,8 @@ void CommandLineParser::SetupEngineCommands() { } }); engine_use_cmd->group(kSubcommands); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineUse(engine_use_cmd, engine_name); + for (const auto& engine : supported_engines_) { + EngineUse(engine_use_cmd, engine); } auto engine_load_cmd = engines_cmd->add_subcommand("load", "Load engine"); @@ -564,9 +556,8 @@ void CommandLineParser::SetupEngineCommands() { } }); engine_load_cmd->group(kSubcommands); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineLoad(engine_load_cmd, engine_name); + for (const auto& engine : supported_engines_) { + EngineLoad(engine_load_cmd, engine); } auto engine_unload_cmd = @@ -582,9 +573,8 @@ void CommandLineParser::SetupEngineCommands() { } }); engine_unload_cmd->group(kSubcommands); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - EngineUnload(engine_unload_cmd, engine_name); + for (const auto& engine : supported_engines_) { + EngineUnload(engine_unload_cmd, engine); } EngineGet(engines_cmd); @@ -756,7 +746,7 @@ void CommandLineParser::EngineInstall(CLI::App* parent, return; try { commands::EngineInstallCmd( - download_service_, cml_data_.config.apiServerHost, + engine_service_, cml_data_.config.apiServerHost, std::stoi(cml_data_.config.apiServerPort), cml_data_.show_menu) .Exec(engine_name, version, src); } catch (const std::exception& e) { @@ -878,20 +868,19 @@ void CommandLineParser::EngineGet(CLI::App* parent) { } }); - for (auto& engine : engine_service_.kSupportEngines) { - std::string engine_name{engine}; - std::string desc = "Get " + engine_name + " status"; + for (const auto& engine : supported_engines_) { + std::string desc = "Get " + engine + " status"; - auto engine_get_cmd = get_cmd->add_subcommand(engine_name, desc); + auto engine_get_cmd = get_cmd->add_subcommand(engine, desc); engine_get_cmd->usage("Usage:\n" + commands::GetCortexBinary() + - " engines get " + engine_name + " [options]"); + " engines get " + engine + " [options]"); engine_get_cmd->group(kEngineGroup); - engine_get_cmd->callback([this, engine_name] { + engine_get_cmd->callback([this, engine] { if (std::exchange(executed_, true)) return; commands::EngineGetCmd().Exec(cml_data_.config.apiServerHost, std::stoi(cml_data_.config.apiServerPort), - engine_name); + engine); }); } } diff --git a/engine/cli/command_line_parser.h b/engine/cli/command_line_parser.h index 896c026d0..14e10e420 100644 --- a/engine/cli/command_line_parser.h +++ b/engine/cli/command_line_parser.h @@ -5,7 +5,6 @@ #include "CLI/CLI.hpp" #include "commands/hardware_list_cmd.h" #include "services/engine_service.h" -#include "services/model_service.h" #include "utils/config_yaml_utils.h" class CommandLineParser { @@ -16,8 +15,6 @@ class CommandLineParser { private: void SetupCommonCommands(); - void SetupInferenceCommands(); - void SetupModelCommands(); void SetupEngineCommands(); @@ -47,8 +44,9 @@ class CommandLineParser { CLI::App app_; std::shared_ptr download_service_; - EngineService engine_service_; - ModelService model_service_; + std::shared_ptr dylib_path_manager_; + std::shared_ptr engine_service_; + std::vector supported_engines_; struct CmlData { std::string model_id; diff --git a/engine/cli/commands/engine_install_cmd.cc b/engine/cli/commands/engine_install_cmd.cc index 491ab0937..85a5def5d 100644 --- a/engine/cli/commands/engine_install_cmd.cc +++ b/engine/cli/commands/engine_install_cmd.cc @@ -12,7 +12,7 @@ bool EngineInstallCmd::Exec(const std::string& engine, const std::string& src) { // Handle local install, if fails, fallback to remote install if (!src.empty()) { - auto res = engine_service_.UnzipEngine(engine, version, src); + auto res = engine_service_->UnzipEngine(engine, version, src); if (res.has_error()) { CLI_LOG(res.error()); return false; diff --git a/engine/cli/commands/engine_install_cmd.h b/engine/cli/commands/engine_install_cmd.h index d50776dc4..2f318b4d7 100644 --- a/engine/cli/commands/engine_install_cmd.h +++ b/engine/cli/commands/engine_install_cmd.h @@ -7,9 +7,9 @@ namespace commands { class EngineInstallCmd { public: - explicit EngineInstallCmd(std::shared_ptr download_service, + explicit EngineInstallCmd(std::shared_ptr engine_service, const std::string& host, int port, bool show_menu) - : engine_service_{EngineService(download_service)}, + : engine_service_{engine_service}, host_(host), port_(port), show_menu_(show_menu), @@ -21,7 +21,7 @@ class EngineInstallCmd { const std::string& src = ""); private: - EngineService engine_service_; + std::shared_ptr engine_service_; std::string host_; int port_; bool show_menu_; diff --git a/engine/cli/commands/engine_list_cmd.cc b/engine/cli/commands/engine_list_cmd.cc index 35584dcd2..0abe32b28 100644 --- a/engine/cli/commands/engine_list_cmd.cc +++ b/engine/cli/commands/engine_list_cmd.cc @@ -13,7 +13,6 @@ // clang-format on namespace commands { - bool EngineListCmd::Exec(const std::string& host, int port) { // Start server if server is not started yet if (!commands::IsServerAlive(host, port)) { @@ -38,15 +37,10 @@ bool EngineListCmd::Exec(const std::string& host, int port) { return false; } - std::vector engines = { - kLlamaEngine, - kOnnxEngine, - kTrtLlmEngine, - }; - std::unordered_map> engine_map; + auto engines = engine_service_->GetSupportedEngineNames().value(); for (const auto& engine : engines) { auto installed_variants = result.value()[engine]; for (const auto& variant : installed_variants) { diff --git a/engine/cli/commands/engine_list_cmd.h b/engine/cli/commands/engine_list_cmd.h index 96ad956b2..1a06126a4 100644 --- a/engine/cli/commands/engine_list_cmd.h +++ b/engine/cli/commands/engine_list_cmd.h @@ -1,11 +1,18 @@ #pragma once #include +#include "services/engine_service.h" namespace commands { class EngineListCmd { public: + explicit EngineListCmd(std::shared_ptr engine_service) + : engine_service_{engine_service} {} + bool Exec(const std::string& host, int port); + + private: + std::shared_ptr engine_service_; }; } // namespace commands diff --git a/engine/cli/commands/run_cmd.cc b/engine/cli/commands/run_cmd.cc index 1b71f1af7..91a813d64 100644 --- a/engine/cli/commands/run_cmd.cc +++ b/engine/cli/commands/run_cmd.cc @@ -94,7 +94,7 @@ void RunCmd::Exec(bool run_detach, // Check if engine existed. If not, download it { - auto is_engine_ready = engine_service_.IsEngineReady(mc.engine); + auto is_engine_ready = engine_service_->IsEngineReady(mc.engine); if (is_engine_ready.has_error()) { throw std::runtime_error(is_engine_ready.error()); } @@ -102,7 +102,7 @@ void RunCmd::Exec(bool run_detach, if (!is_engine_ready.value()) { CTL_INF("Engine " << mc.engine << " is not ready. Proceed to install.."); - if (!EngineInstallCmd(download_service_, host_, port_, false) + if (!EngineInstallCmd(engine_service_, host_, port_, false) .Exec(mc.engine)) { return; } else { diff --git a/engine/cli/commands/run_cmd.h b/engine/cli/commands/run_cmd.h index c0f6a4eb2..b22b064f9 100644 --- a/engine/cli/commands/run_cmd.h +++ b/engine/cli/commands/run_cmd.h @@ -12,12 +12,11 @@ std::optional SelectLocalModel(std::string host, int port, class RunCmd { public: explicit RunCmd(std::string host, int port, std::string model_handle, - std::shared_ptr download_service) + std::shared_ptr engine_service) : host_{std::move(host)}, port_{port}, model_handle_{std::move(model_handle)}, - download_service_(download_service), - engine_service_{EngineService(download_service)} {}; + engine_service_{engine_service} {}; void Exec(bool chat_flag, const std::unordered_map& options); @@ -26,8 +25,6 @@ class RunCmd { std::string host_; int port_; std::string model_handle_; - - std::shared_ptr download_service_; - EngineService engine_service_; + std::shared_ptr engine_service_; }; } // namespace commands diff --git a/engine/cli/commands/server_start_cmd.cc b/engine/cli/commands/server_start_cmd.cc index 3d52f3d25..3d6045cd5 100644 --- a/engine/cli/commands/server_start_cmd.cc +++ b/engine/cli/commands/server_start_cmd.cc @@ -112,7 +112,9 @@ bool ServerStartCmd::Exec(const std::string& host, int port, return false; } else if (pid == 0) { // Some engines requires to add lib search path before process being created - EngineService().RegisterEngineLibPath(); + auto download_srv = std::make_shared(); + auto dylib_path_mng = std::make_shared(); + EngineService(download_srv, dylib_path_mng).RegisterEngineLibPath(); std::string p = cortex_utils::GetCurrentPath() + "/" + exe; execl(p.c_str(), exe.c_str(), "--start-server", "--config_file_path", @@ -131,5 +133,4 @@ bool ServerStartCmd::Exec(const std::string& host, int port, #endif return true; } - }; // namespace commands diff --git a/engine/controllers/engines.cc b/engine/controllers/engines.cc index 1d0223d9a..a92d6805f 100644 --- a/engine/controllers/engines.cc +++ b/engine/controllers/engines.cc @@ -3,9 +3,9 @@ #include "utils/archive_utils.h" #include "utils/cortex_utils.h" #include "utils/engine_constants.h" -#include "utils/http_util.h" #include "utils/logging_utils.h" #include "utils/string_utils.h" + namespace { // Need to change this after we rename repositories std::string NormalizeEngine(const std::string& engine) { @@ -24,8 +24,8 @@ void Engines::ListEngine( const HttpRequestPtr& req, std::function&& callback) const { Json::Value ret; - auto engine_names = engine_service_->GetSupportedEngineNames().value(); - for (const auto& engine : engine_names) { + auto engines = engine_service_->GetSupportedEngineNames().value(); + for (const auto& engine : engines) { auto installed_engines = engine_service_->GetInstalledEngineVariants(engine); if (installed_engines.has_error()) { @@ -37,6 +37,7 @@ void Engines::ListEngine( } ret[engine] = variants; } + // Add remote engine auto remote_engines = engine_service_->GetEngines(); if (remote_engines.has_value()) { @@ -49,7 +50,6 @@ void Engines::ListEngine( } } } - auto resp = cortex_utils::CreateCortexHttpJsonResponse(ret); resp->setStatusCode(k200OK); callback(resp); diff --git a/engine/cortex-common/EngineI.h b/engine/cortex-common/EngineI.h index b456cb109..b796ebaed 100644 --- a/engine/cortex-common/EngineI.h +++ b/engine/cortex-common/EngineI.h @@ -8,15 +8,11 @@ #include "trantor/utils/Logger.h" class EngineI { public: - struct RegisterLibraryOption { - std::vector paths; - }; - struct EngineLoadOption { // engine std::filesystem::path engine_path; - std::filesystem::path cuda_path; - bool custom_engine_path; + std::filesystem::path deps_path; + bool is_custom_engine_path; // logging std::filesystem::path log_path; @@ -25,16 +21,11 @@ class EngineI { }; struct EngineUnloadOption { - bool unload_dll; + // place holder for now }; virtual ~EngineI() {} - /** - * Being called before starting process to register dependencies search paths. - */ - virtual void RegisterLibraryPath(RegisterLibraryOption opts) = 0; - virtual void Load(EngineLoadOption opts) = 0; virtual void Unload(EngineUnloadOption opts) = 0; diff --git a/engine/main.cc b/engine/main.cc index 13583dc00..8ca5ffd1f 100644 --- a/engine/main.cc +++ b/engine/main.cc @@ -26,6 +26,7 @@ #include "services/thread_service.h" #include "utils/archive_utils.h" #include "utils/cortex_utils.h" +#include "utils/dylib_path_manager.h" #include "utils/event_processor.h" #include "utils/file_logger.h" #include "utils/file_manager_utils.h" @@ -125,6 +126,8 @@ void RunServer(std::optional port, bool ignore_cout) { cortex::event::EventProcessor event_processor(event_queue_ptr); auto data_folder_path = file_manager_utils::GetCortexDataPath(); + // utils + auto dylib_path_manager = std::make_shared(); auto file_repo = std::make_shared(data_folder_path); auto msg_repo = std::make_shared(data_folder_path); @@ -139,7 +142,8 @@ void RunServer(std::optional port, bool ignore_cout) { auto config_service = std::make_shared(); auto download_service = std::make_shared(event_queue_ptr, config_service); - auto engine_service = std::make_shared(download_service); + auto engine_service = + std::make_shared(download_service, dylib_path_manager); auto inference_svc = std::make_shared(engine_service); auto model_src_svc = std::make_shared(); diff --git a/engine/services/engine_service.cc b/engine/services/engine_service.cc index 4f2122f6b..035ef4a4e 100644 --- a/engine/services/engine_service.cc +++ b/engine/services/engine_service.cc @@ -711,23 +711,42 @@ cpp::result EngineService::LoadEngine( auto custom_engine_path = engine_dir_path_res.value().second; try { + auto cuda_path = file_manager_utils::GetCudaToolkitPath(ne); + +#if defined(_WIN32) || defined(_WIN64) + // register deps + std::vector paths{}; + paths.push_back(std::move(cuda_path)); + paths.push_back(std::move(engine_dir_path)); + + CTL_DBG("Registering dylib for " + << ne << " with " << std::to_string(paths.size()) << " paths."); + for (const auto& path : paths) { + CTL_DBG("Registering path: " << path.string()); + } + + auto reg_result = dylib_path_manager_->RegisterPath(ne, paths); + if (reg_result.has_error()) { + CTL_DBG("Failed register lib paths for: " << ne); + } else { + CTL_DBG("Registered lib paths for: " << ne); + } +#endif + auto dylib = std::make_unique(engine_dir_path.string(), "engine"); auto config = file_manager_utils::GetCortexConfig(); - - auto log_path = - std::filesystem::path(config.logFolderPath) / - std::filesystem::path( - config.logLlamaCppPath); // for now seems like we use same log path + auto log_path = std::filesystem::path(config.logFolderPath) / + std::filesystem::path(config.logLlamaCppPath); // init auto func = dylib->get_function("get_engine"); auto engine_obj = func(); auto load_opts = EngineI::EngineLoadOption{ .engine_path = engine_dir_path, - .cuda_path = file_manager_utils::GetCudaToolkitPath(ne), - .custom_engine_path = custom_engine_path, + .deps_path = cuda_path, + .is_custom_engine_path = custom_engine_path, .log_path = log_path, .max_log_lines = config.maxLogLines, .log_level = logging_utils_helper::global_log_level, @@ -753,27 +772,32 @@ void EngineService::RegisterEngineLibPath() { try { auto engine_dir_path_res = GetEngineDirPath(engine); if (engine_dir_path_res.has_error()) { - CTL_ERR( + CTL_WRN( "Could not get engine dir path: " << engine_dir_path_res.error()); continue; } auto engine_dir_path = engine_dir_path_res.value().first; auto custom_engine_path = engine_dir_path_res.value().second; - - auto dylib = std::make_unique(engine_dir_path.string(), - "engine"); - auto cuda_path = file_manager_utils::GetCudaToolkitPath(ne); - // init - auto func = dylib->get_function("get_engine"); - auto engine = func(); + + // register deps std::vector paths{}; - auto register_opts = EngineI::RegisterLibraryOption{ - .paths = paths, - }; - engine->RegisterLibraryPath(register_opts); - delete engine; - CTL_DBG("Register lib path for: " << engine); + paths.push_back(std::move(cuda_path)); + paths.push_back(std::move(engine_dir_path)); + + CTL_DBG("Registering dylib for " + << ne << " with " << std::to_string(paths.size()) << " paths."); + for (const auto& path : paths) { + CTL_DBG("Registering path: " << path.string()); + } + + auto reg_result = dylib_path_manager_->RegisterPath(ne, paths); + if (reg_result.has_error()) { + CTL_WRN("Failed register lib path for " << engine); + } else { + CTL_DBG("Registered lib path for " << engine); + } + } catch (const std::exception& e) { CTL_WRN("Failed to registering engine lib path: " << e.what()); } @@ -832,10 +856,14 @@ cpp::result EngineService::UnloadEngine( } if (std::holds_alternative(engines_[ne].engine)) { LOG_INFO << "Unloading engine " << ne; + auto unreg_result = dylib_path_manager_->Unregister(ne); + if (unreg_result.has_error()) { + CTL_DBG("Failed unregister lib paths for: " << ne); + } else { + CTL_DBG("Unregistered lib paths for: " << ne); + } auto* e = std::get(engines_[ne].engine); - auto unload_opts = EngineI::EngineUnloadOption{ - .unload_dll = true, - }; + auto unload_opts = EngineI::EngineUnloadOption{}; e->Unload(unload_opts); delete e; engines_.erase(ne); diff --git a/engine/services/engine_service.h b/engine/services/engine_service.h index 8299655f2..9253eccf1 100644 --- a/engine/services/engine_service.h +++ b/engine/services/engine_service.h @@ -16,6 +16,7 @@ #include "services/download_service.h" #include "utils/cpuid/cpu_info.h" #include "utils/dylib.h" +#include "utils/dylib_path_manager.h" #include "utils/engine_constants.h" #include "utils/github_release_utils.h" #include "utils/result.hpp" @@ -56,6 +57,7 @@ class EngineService : public EngineServiceI { std::mutex engines_mutex_; std::unordered_map engines_{}; std::shared_ptr download_service_; + std::shared_ptr dylib_path_manager_; struct HardwareInfo { std::unique_ptr sys_inf; @@ -65,18 +67,15 @@ class EngineService : public EngineServiceI { HardwareInfo hw_inf_; public: - const std::vector kSupportEngines = { - kLlamaEngine, kOnnxEngine, kTrtLlmEngine}; - - explicit EngineService(std::shared_ptr download_service) + explicit EngineService( + std::shared_ptr download_service, + std::shared_ptr dylib_path_manager) : download_service_{download_service}, + dylib_path_manager_{dylib_path_manager}, hw_inf_{.sys_inf = system_info_utils::GetSystemInfo(), .cuda_driver_version = system_info_utils::GetDriverAndCudaVersion().second} {} - // just for initialize supported engines - EngineService() {}; - std::vector GetEngineInfoList() const; /** diff --git a/engine/services/model_service.cc b/engine/services/model_service.cc index 15fee15be..6a45733d3 100644 --- a/engine/services/model_service.cc +++ b/engine/services/model_service.cc @@ -970,9 +970,7 @@ cpp::result ModelService::GetModelStatus( if (status == drogon::k200OK) { return true; } else { - CTL_WRN("Model failed to get model status with status code: " << status); - return cpp::fail("Model failed to get model status: " + - data["message"].asString()); + return cpp::fail(data["message"].asString()); } } catch (const std::exception& e) { return cpp::fail("Fail to get model status with ID '" + model_handle + diff --git a/engine/utils/config_yaml_utils.cc b/engine/utils/config_yaml_utils.cc index c7a696df4..8fbfe1dbe 100644 --- a/engine/utils/config_yaml_utils.cc +++ b/engine/utils/config_yaml_utils.cc @@ -84,7 +84,8 @@ CortexConfig CortexConfigMgr::FromYaml(const std::string& path, !node["proxyUsername"] || !node["proxyPassword"] || !node["verifyPeerSsl"] || !node["verifyHostSsl"] || !node["verifyProxySsl"] || !node["verifyProxyHostSsl"] || - !node["sslCertPath"] || !node["sslKeyPath"] || !node["noProxy"]); + !node["supportedEngines"] || !node["sslCertPath"] || + !node["sslKeyPath"] || !node["noProxy"]); CortexConfig config = { .logFolderPath = node["logFolderPath"] @@ -172,6 +173,10 @@ CortexConfig CortexConfigMgr::FromYaml(const std::string& path, : default_cfg.sslCertPath, .sslKeyPath = node["sslKeyPath"] ? node["sslKeyPath"].as() : default_cfg.sslKeyPath, + .supportedEngines = + node["supportedEngines"] + ? node["supportedEngines"].as>() + : default_cfg.supportedEngines, }; if (should_update_config) { l.unlock(); diff --git a/engine/utils/dylib_path_manager.cc b/engine/utils/dylib_path_manager.cc new file mode 100644 index 000000000..3d10fc8ff --- /dev/null +++ b/engine/utils/dylib_path_manager.cc @@ -0,0 +1,129 @@ +#include "dylib_path_manager.h" +#include "utils/logging_utils.h" + +namespace cortex { + +cpp::result DylibPathManager::RegisterPath( + const std::string& key, std::vector paths) { +#if defined(_WIN32) || defined(_WIN64) + std::vector dylib_paths; + for (const auto& path : paths) { + if (!std::filesystem::exists(path)) { + return cpp::fail("Path does not exist: " + path.string()); + } + + std::wstring_convert> converter; + std::wstring wide_path = converter.from_bytes(path.string()); + + auto cookie = AddDllDirectory(wide_path.c_str()); + if (cookie == nullptr) { + CTL_ERR("Failed to added DLL directory: " << path.string()); + + // Clean up any paths we've already added + for (auto& dylib_path : dylib_paths) { + CTL_DBG("Cleaning DLL path: " + dylib_path.path.string()); + RemoveDllDirectory(dylib_path.cookie); + } + return cpp::fail("Failed to add DLL directory: " + path.string()); + } else { + CTL_DBG("Added DLL directory: " << path.string()); + } + + dylib_paths.push_back({path, cookie}); + } + dylib_map_[key] = std::move(dylib_paths); + +#elif defined(__linux__) + // For Linux, we need to modify LD_LIBRARY_PATH + std::vector dylib_paths; + std::stringstream new_path; + bool first = true; + + // First verify all paths exist + for (const auto& path : paths) { + if (!std::filesystem::exists(path)) { + return cpp::fail("Path does not exist: " + path.string()); + } + } + + // Get current LD_LIBRARY_PATH + const char* current_path = getenv(kLdLibraryPath); + std::string current_paths = current_path ? current_path : ""; + CTL_DBG("Current paths: " << current_paths); + + // Add new paths + for (const auto& path : paths) { + if (!first) { + new_path << ":"; + } + new_path << path.string(); + dylib_paths.push_back({path}); + first = false; + } + + // Append existing paths if they exist + if (!current_paths.empty()) { + new_path << ":" << current_paths; + } + CTL_DBG("New paths: " << new_path.str()); + // Set the new LD_LIBRARY_PATH + if (setenv(kLdLibraryPath, new_path.str().c_str(), 1) != 0) { + CTL_ERR("Failed to set path!!!"); + return cpp::fail("Failed to set " + std::string(kLdLibraryPath)); + } + + CTL_DBG("After set path: " << getenv(kLdLibraryPath)); + + dylib_map_[key] = std::move(dylib_paths); +#endif + + return {}; +} + +cpp::result DylibPathManager::Unregister( + const std::string& key) { + auto it = dylib_map_.find(key); + if (it == dylib_map_.end()) { + return cpp::fail("Key not found: " + key); + } + +#if defined(_WIN32) || defined(_WIN64) + // For Windows, remove each DLL directory + for (auto& dylib_path : it->second) { + if (!RemoveDllDirectory(dylib_path.cookie)) { + return cpp::fail("Failed to remove DLL directory: " + + dylib_path.path.string()); + } + } + +#elif defined(__linux__) + // For Linux, we need to rebuild LD_LIBRARY_PATH without the removed paths + const char* current_path = getenv(kLdLibraryPath); + if (current_path) { + std::string paths = current_path; + for (const auto& dylib_path : it->second) { + std::string path_str = dylib_path.path.string(); + size_t pos = paths.find(path_str); + if (pos != std::string::npos) { + // Remove the path and the following colon (or preceding colon if it's at the end) + if (pos > 0 && paths[pos - 1] == ':') { + paths.erase(pos - 1, path_str.length() + 1); + } else if (pos + path_str.length() < paths.length() && + paths[pos + path_str.length()] == ':') { + paths.erase(pos, path_str.length() + 1); + } else { + paths.erase(pos, path_str.length()); + } + } + } + + if (setenv(kLdLibraryPath, paths.c_str(), 1) != 0) { + return cpp::fail("Failed to update " + std::string(kLdLibraryPath)); + } + } +#endif + + dylib_map_.erase(it); + return {}; +} +} // namespace cortex diff --git a/engine/utils/dylib_path_manager.h b/engine/utils/dylib_path_manager.h new file mode 100644 index 000000000..bfdff7c7e --- /dev/null +++ b/engine/utils/dylib_path_manager.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include "utils/result.hpp" + +#if defined(_WIN32) +#include +#include +#include +#endif + +namespace cortex { +class DylibPathManager { + // for linux + constexpr static auto kLdLibraryPath{"LD_LIBRARY_PATH"}; + + struct DylibPath { + std::filesystem::path path; +#if defined(_WIN32) || defined(_WIN64) + DLL_DIRECTORY_COOKIE cookie; +#endif + }; + + public: + cpp::result RegisterPath( + const std::string& key, std::vector paths); + + cpp::result Unregister(const std::string& key); + + private: + std::unordered_map> dylib_map_; +}; +} // namespace cortex