From 624bba121f746c3a6fb7ae343a001cf4bda68efc Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 6 Jun 2016 19:54:20 +0200 Subject: [PATCH] Remove hardcoded path to postgresql backend and make the search dynamic --- CMakeLists.txt | 2 +- src/backends/backend_loader.cpp | 23 ++++++++++++++++--- src/common/settings.cpp | 39 +++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3f19f6..f0dd066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ if ("${DINDEXER_CONFIG_FILE}" STREQUAL "") endif() message(STATUS "Config file set to \"${DINDEXER_CONFIG_FILE}\"") -find_package(Boost 1.53.0 REQUIRED COMPONENTS program_options filesystem) +find_package(Boost 1.53.0 REQUIRED COMPONENTS program_options filesystem system) find_package(PostgreSQL 8.3 REQUIRED) find_package(YamlCpp 0.5.1 REQUIRED) import_libpqtypes_project("${PostgreSQL_INCLUDE_DIRS}" "-O3 ${march_flag}") diff --git a/src/backends/backend_loader.cpp b/src/backends/backend_loader.cpp index 3aa8547..05b5909 100644 --- a/src/backends/backend_loader.cpp +++ b/src/backends/backend_loader.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace dindb { namespace { @@ -34,9 +35,22 @@ namespace dindb { assert(parSOHandle); assert(parConfig); - auto create = reinterpret_cast(dlsym(parSOHandle, "dindexer_create_backend")); - auto destroy = reinterpret_cast(dlsym(parSOHandle, "dindexer_destroy_backend")); + const char* const fun_name_create = "dindexer_create_backend"; + const char* const fun_name_destroy = "dindexer_destroy_backend"; + auto create = reinterpret_cast(dlsym(parSOHandle, fun_name_create)); + auto destroy = reinterpret_cast(dlsym(parSOHandle, fun_name_destroy)); + + if (not create) { + std::ostringstream oss; + oss << "Unable to find function " << fun_name_create; + throw std::runtime_error(oss.str()); + } + if (not destroy) { + std::ostringstream oss; + oss << "Unable to find function " << fun_name_destroy; + throw std::runtime_error(oss.str()); + } return BackendPtr(create(parConfig), destroy); } @@ -65,7 +79,10 @@ namespace dindb { using SoHandle = std::unique_ptr; auto handle = SoHandle(dlopen(parSOPath.c_str(), RTLD_LAZY), &dlclose); - return backend_name(handle.get()); + if (handle) + return backend_name(handle.get()); + else + return std::string(); } BackendPlugin::BackendPlugin() : diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 23eeb7d..cf68d48 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -16,33 +16,40 @@ */ #include "dindexer-common/settings.hpp" +#include "dindexer-common/split_tags.hpp" #include "dindexerConfig.h" #include #include #include #include #include +#include +#include namespace dinlib { namespace { std::string expand ( const char* parString ); - std::string find_plugin_by_name ( const std::string& parName ); + std::string find_plugin_by_name ( const std::vector& parSearchPaths, const std::string& parName ); void throw_if_plugin_failed ( const dindb::BackendPlugin& parPlugin, const std::string& parPluginPath, const std::string& parIntendedName ); } //unnamed namespace void load_settings (const std::string& parPath, dinlib::Settings& parOut, bool parExpand) { const std::string path = (parExpand ? expand(parPath.c_str()) : parPath); + std::string search_paths(ACTIONS_SEARCH_PATH); auto settings = YAML::LoadFile(path); - if (not settings["backend_name"]) { + if (not settings["backend_name"]) throw std::runtime_error("No backend_name given in the config file"); - } + if (settings["backend_paths"]) + search_paths += ":" + settings["backend_paths"].as(); parOut.backend_name = settings["backend_name"].as(); const std::string backend_settings_section = parOut.backend_name + "_settings"; if (settings[backend_settings_section]) { auto settings_node = settings[backend_settings_section]; - const std::string plugin_path = find_plugin_by_name(parOut.backend_name); + const std::string plugin_path = find_plugin_by_name(split_and_trim(search_paths, ':'), parOut.backend_name); + if (plugin_path.empty()) + throw std::runtime_error(std::string("Unable to find any suitable plugin with the specified name \"") + parOut.backend_name + "\""); parOut.backend_plugin = dindb::BackendPlugin(plugin_path, &settings_node); throw_if_plugin_failed(parOut.backend_plugin, plugin_path, parOut.backend_name); } @@ -61,14 +68,24 @@ namespace dinlib { return oss.str(); } - std::string find_plugin_by_name (const std::string& parName) { - //assert(false); //not implemented - //TODO: write a proper implementation - std::string path = ACTIONS_SEARCH_PATH; - path += "/backends/postgresql/libdindexer-backend-postgresql.so"; + std::string find_plugin_by_name (const std::vector& parSearchPaths, const std::string& parName) { + using boost::filesystem::path; + using boost::filesystem::is_directory; + using boost::filesystem::directory_iterator; + using boost::filesystem::directory_entry; + using boost::make_iterator_range; - assert(dindb::backend_name(path) == parName); - return path; + for (auto search_path : parSearchPaths) { + const std::string search_path_cpy(search_path.begin(), search_path.end()); + path curr_path(search_path_cpy); + auto listing = make_iterator_range(directory_iterator(curr_path), directory_iterator()); + for (const directory_entry& entry : listing) { + auto current_full_path = entry.path().string(); + if (not is_directory(entry) and dindb::backend_name(current_full_path) == parName) + return current_full_path; + } + } + return std::string(); } void throw_if_plugin_failed (const dindb::BackendPlugin& parPlugin, const std::string& parPluginPath, const std::string& parIntendedName) {