From a1490c30968118b4c69f6837966b3986a47177fe Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 6 Jun 2016 19:52:42 +0200 Subject: [PATCH 1/3] Make split_tags a bit more generic so I can reuse it I need it in an upcoming commit where I want to split on ':' --- include/dindexer-common/split_tags.hpp | 1 + src/common/split_tags.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/dindexer-common/split_tags.hpp b/include/dindexer-common/split_tags.hpp index 149cc25..3005751 100644 --- a/include/dindexer-common/split_tags.hpp +++ b/include/dindexer-common/split_tags.hpp @@ -24,6 +24,7 @@ #include "helpers/compatibility.h" namespace dinlib { + std::vector split_and_trim ( const std::string& parList, char parSeparator ) a_pure; std::vector split_tags ( const std::string& parCommaSeparatedList ) a_pure; } //namespace dinlib diff --git a/src/common/split_tags.cpp b/src/common/split_tags.cpp index 4ba7275..931a8d5 100644 --- a/src/common/split_tags.cpp +++ b/src/common/split_tags.cpp @@ -26,6 +26,10 @@ namespace dinlib { std::vector split_tags (const std::string& parCommaSeparatedList) { + return split_and_trim(parCommaSeparatedList, ','); + } + + std::vector split_and_trim (const std::string& parList, char parSeparator) { using OutRange = boost::iterator_range; using boost::token_finder; using boost::adaptors::transformed; @@ -42,7 +46,7 @@ namespace dinlib { //http://www.boost.org/doc/libs/1_60_0/doc/html/boost/algorithm/token_finder.html //https://stackoverflow.com/questions/20781090/difference-between-boostsplit-vs-boostiter-split return boost::copy_range>( - iter_split(out_range, parCommaSeparatedList, token_finder([](char c){return ','==c;})) | + iter_split(out_range, parList, token_finder([parSeparator](char c){return parSeparator==c;})) | transformed([](const OutRange& r){return trim_copy(r);}) | transformed([](const OutRange& r){return string_ref(&*r.begin(), r.size());}) | filtered([](const string_ref& r){return not r.empty();}) From 624bba121f746c3a6fb7ae343a001cf4bda68efc Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 6 Jun 2016 19:54:20 +0200 Subject: [PATCH 2/3] 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) { From 3fe962a8e515fb3fc96b3c10b8f9810557868c34 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 6 Jun 2016 20:24:05 +0200 Subject: [PATCH 3/3] Make symlink to postgresql backend This is helpful so when running dindexer in a dev environment you don't need to list all the possible paths to every backend. Symlinks to all backends will all be in the same place. --- dindexer.yml | 1 + src/backends/CMakeLists.txt | 10 +++++++++- src/backends/postgresql/CMakeLists.txt | 1 + src/common/settings.cpp | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/dindexer.yml b/dindexer.yml index 38242d4..0f1330f 100644 --- a/dindexer.yml +++ b/dindexer.yml @@ -7,3 +7,4 @@ postgresql_settings: dbname: dindexer port: 5432 address: 200.100.200.100 +backend_paths: path to your build_dir/src/backend diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 0ac6613..302b2e8 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,5 +1,14 @@ project(${bare_name}-backend CXX) +set(BACKEND_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") +function(ln_backend backend_name) + add_custom_command(TARGET "${backend_name}" POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink $ ${BACKEND_BINARY_DIR}/$ + DEPENDS ${BACKEND_BINARY_DIR}/$ + COMMENT "Creating symlink to ${backend_name}" + ) +endfunction() + add_library(${PROJECT_NAME} STATIC backend_loader.cpp ) @@ -25,5 +34,4 @@ target_link_libraries(${PROJECT_NAME} #) add_subdirectory(postgresql) - add_dependencies(${PROJECT_NAME} ${bare_name}-backend-postgresql) diff --git a/src/backends/postgresql/CMakeLists.txt b/src/backends/postgresql/CMakeLists.txt index 89b8680..486d5b0 100644 --- a/src/backends/postgresql/CMakeLists.txt +++ b/src/backends/postgresql/CMakeLists.txt @@ -23,3 +23,4 @@ install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib/static ) +ln_backend(${PROJECT_NAME}) diff --git a/src/common/settings.cpp b/src/common/settings.cpp index cf68d48..95b6b45 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -35,7 +35,7 @@ namespace dinlib { 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); + std::string search_paths; auto settings = YAML::LoadFile(path);