diff --git a/.github/workflows/python-bindings.yml b/.github/workflows/python-bindings.yml index 32c32d6..72c81d8 100644 --- a/.github/workflows/python-bindings.yml +++ b/.github/workflows/python-bindings.yml @@ -14,18 +14,19 @@ jobs: name: "Test python bindings" strategy: matrix: - on: [ 'ubuntu-24.04', 'macos-15-intel' , 'macos-26' ] + on: [ 'ubuntu-24.04', 'macos-15-intel', 'macos-26', 'windows-2022', 'windows-2025' ] python: [ '3.10', '3.11', '3.12', '3.13' ] runs-on: ${{matrix.on}} env: - INSTALL_PREFIX: "/usr/local" + INSTALL_PREFIX: ${{ startsWith(matrix.on, 'windows-') && format('{0}\install', github.workspace) || '/usr/local' }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v6 with: python-version: ${{matrix.python}} + - name: "Install packages ubuntu" if: ${{ startsWith(matrix.on, 'ubuntu-') }} run: sudo apt install -y ninja-build g++ @@ -38,7 +39,13 @@ jobs: if: ${{ startsWith(matrix.on, 'macos-') }} run: brew install ninja gcc cmake - - name: "Run CMake" + - name: "Install Windows packages" + if: ${{ startsWith(matrix.on, 'windows-') }} + shell: pwsh + run: choco install cmake ninja --yes --installargs 'ADD_CMAKE_TO_PATH=System' + + - name: "Run CMake (UNIX)" + if: ${{ !startsWith(matrix.on, 'windows-') }} run: | cmake -DCMAKE_BUILD_TYPE=Release \ -G Ninja \ @@ -47,11 +54,33 @@ jobs: cmake --build ../build -j $(nproc) sudo cmake --install ../build --prefix $INSTALL_PREFIX + - name: "Run CMake (Windows)" + if: ${{ startsWith(matrix.on, 'windows-') }} + shell: pwsh + run: | + cmake -G "Ninja" ` + -DCMAKE_BUILD_TYPE=Release ` + -B ../build ` + -S $env:GITHUB_WORKSPACE + cmake --build ../build --parallel + cmake --install ../build --prefix $env:INSTALL_PREFIX + - name: "Install python test environment" - run: python -m pip install -r ${GITHUB_WORKSPACE}/test-requirement.txt + run: python -m pip install -r test-requirement.txt + + - name: "Run Python tests (WINDOWS)" + if: ${{ startsWith(matrix.on, 'windows-') }} + shell: bash + run: | + PYBIND_FILE=$INSTALL_PREFIX\\lib\\python\\$(dir $INSTALL_PREFIX\\lib\\python | head -n 1) + export CAPIO_CL_PY_BINDING_PATH=$(cygpath -m "$PYBIND_FILE") + echo "Python module path: $CAPIO_CL_PY_BINDING_PATH" + pytest tests/python/test_* - - name: "Run python tests" + - name: "Run Python tests (UNIX)" + if: ${{ !startsWith(matrix.on, 'windows-') }} + shell: bash run: | export CAPIO_CL_PY_BINDING_PATH=$(realpath $INSTALL_PREFIX/lib/python/py_capio_cl*) - echo "Python module path: $CAPIO_CL_PY_BINDING_PATH" + echo "Python module path: $CAPIO_CL_PY_BINDING_PATH" pytest ${GITHUB_WORKSPACE}/tests/python/test_* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c5112a6..ac7fd8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,21 +87,35 @@ if (BUILD_PYTHON_BINDINGS) ) - # Make sure the binding sees the CAPIO CL headers & links against the core lib - target_link_libraries(${PYTHON_BIND_NAME} - PRIVATE libcapio_cl - ) + if (WIN32) + target_link_libraries(${PYTHON_BIND_NAME} + PRIVATE libcapio_cl ws2_32 shlwapi + ) + else() + target_link_libraries(${PYTHON_BIND_NAME} + PRIVATE libcapio_cl + ) + endif () + target_include_directories(${PYTHON_BIND_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) - install(TARGETS ${PYTHON_BIND_NAME} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/python - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/python - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) + if (WIN32) + install(TARGETS ${PYTHON_BIND_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\\python + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}\\python + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}\\python + ) + else () + install(TARGETS ${PYTHON_BIND_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/python + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/python + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + endif () endif () @@ -128,6 +142,10 @@ if (CAPIO_CL_BUILD_TESTS) GTest::gtest_main ) + if (WIN32) + target_link_libraries(CAPIO_CL_tests PRIVATE ws2_32 shlwapi) + endif () + target_include_directories(CAPIO_CL_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src diff --git a/capiocl.hpp b/capiocl.hpp index 5558e5a..af36b11 100644 --- a/capiocl.hpp +++ b/capiocl.hpp @@ -5,10 +5,16 @@ #include #include #include -#include #include #include +#ifdef _WIN32 +#include +#pragma comment(lib, "Ws2_32.lib") +#else +#include +#endif + #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 1024 #endif @@ -84,7 +90,7 @@ class Engine { /** * Hash map used to store the configuration from CAPIO-CL */ - std::unordered_map, ///< Producers list [0] std::vector, ///< Consumers list [1] std::string, ///< Commit rule [2] @@ -94,7 +100,7 @@ class Engine { bool, ///< Is file (false = directory) [6] long, ///< Commit-on-close count [7] long, ///< Expected directory file count [8] - std::vector, ///< File dependencies [9] + std::vector, ///< File dependencies [9] bool>> ///< Store in FS (false = memory) [10] _locations; @@ -160,10 +166,10 @@ class Engine { * @param exclude Whether the file/directory is excluded. * @param dependencies List of dependent files. */ - void add(std::string &path, std::vector &producers, + void add(std::filesystem::path &path, std::vector &producers, std::vector &consumers, const std::string &commit_rule, const std::string &fire_rule, bool permanent, bool exclude, - const std::vector &dependencies); + const std::vector &dependencies); /** * @brief Add a new producer to a file entry. @@ -171,7 +177,7 @@ class Engine { * @param path File path. * @param producer Application name of the producer. */ - void addProducer(const std::string &path, std::string &producer); + void addProducer(const std::filesystem::path &path, std::string &producer); /** * @brief Add a new consumer to a file entry. @@ -179,7 +185,7 @@ class Engine { * @param path File path. * @param consumer Application name of the consumer. */ - void addConsumer(const std::string &path, std::string &consumer); + void addConsumer(const std::filesystem::path &path, std::string &consumer); /** * @brief Add a new file dependency, when rule is commit_on_file @@ -187,7 +193,7 @@ class Engine { * @param path * @param file_dependency */ - void addFileDependency(const std::string &path, std::string &file_dependency); + void addFileDependency(const std::filesystem::path &path, std::string &file_dependency); /** * @brief Create a new CAPIO file entry. @@ -197,14 +203,14 @@ class Engine { * * @param path Path of the new file. */ - void newFile(const std::string &path); + void newFile(const std::filesystem::path &path); /** * @brief Remove a file from the configuration. * * @param path Path of the file to remove. */ - void remove(const std::string &path); + void remove(const std::filesystem::path &path); /** * @brief Set the commit rule of a file. @@ -212,7 +218,7 @@ class Engine { * @param path File path. * @param commit_rule Commit rule string. */ - void setCommitRule(const std::string &path, const std::string &commit_rule); + void setCommitRule(const std::filesystem::path &path, const std::string &commit_rule); /** * @brief Set the fire rule of a file. @@ -220,7 +226,7 @@ class Engine { * @param path File path. * @param fire_rule Fire rule string. */ - void setFireRule(const std::string &path, const std::string &fire_rule); + void setFireRule(const std::filesystem::path &path, const std::string &fire_rule); /** * @brief Mark a file as permanent or not. @@ -228,7 +234,7 @@ class Engine { * @param path File path. * @param value true to mark permanent, false otherwise. */ - void setPermanent(const std::string &path, bool value); + void setPermanent(const std::filesystem::path &path, bool value); /** * @brief Mark a file as excluded or not. @@ -236,21 +242,21 @@ class Engine { * @param path File path. * @param value true to exclude, false otherwise. */ - void setExclude(const std::string &path, bool value); + void setExclude(const std::filesystem::path &path, bool value); /** * @brief Mark a path as a directory. * * @param path Path to mark. */ - void setDirectory(const std::string &path); + void setDirectory(const std::filesystem::path &path); /** * @brief Mark a path as a file. * * @param path Path to mark. */ - void setFile(const std::string &path); + void setFile(const std::filesystem::path &path); /** * @brief Set the commit-on-close counter. @@ -260,7 +266,7 @@ class Engine { * @param path File path. * @param num Number of close operations before commit. */ - void setCommitedCloseNumber(const std::string &path, long num); + void setCommitedCloseNumber(const std::filesystem::path &path, long num); /** * @brief Set the expected number of files in a directory. @@ -268,7 +274,7 @@ class Engine { * @param path Directory path. * @param num Expected file count. */ - void setDirectoryFileCount(const std::string &path, long num); + void setDirectoryFileCount(const std::filesystem::path &path, long num); /** * @brief Set the dependencies of a file. @@ -279,7 +285,7 @@ class Engine { * @param dependencies List of dependent files. */ void setFileDeps(const std::filesystem::path &path, - const std::vector &dependencies); + const std::vector &dependencies); /** * @brief Store the file in memory only. @@ -304,31 +310,32 @@ class Engine { * @param path Directory path. * @return Expected file count. */ - long getDirectoryFileCount(const std::string &path); + long getDirectoryFileCount(const std::filesystem::path &path); /// @brief Get the commit rule of a file. - std::string getCommitRule(const std::string &path); + std::string getCommitRule(const std::filesystem::path &path); /// @brief Get the fire rule of a file. - std::string getFireRule(const std::string &path); + std::string getFireRule(const std::filesystem::path &path); /// @brief Get the producers of a file. - std::vector getProducers(const std::string &path); + std::vector getProducers(const std::filesystem::path &path); /// @brief Get the consumers of a file. - std::vector getConsumers(const std::string &path); + std::vector getConsumers(const std::filesystem::path &path); /// @brief Get the commit-on-close counter for a file. long getCommitCloseCount(std::filesystem::path::iterator::reference path) const; /// @brief Get file dependencies. - std::vector getCommitOnFileDependencies(const std::filesystem::path &path); + std::vector + getCommitOnFileDependencies(const std::filesystem::path &path); /// @brief Get the list of files stored in memory. - std::vector getFileToStoreInMemory(); + std::vector getFileToStoreInMemory(); /// @brief Get the home node of a file. - std::string getHomeNode(const std::string &path); + std::string getHomeNode(const std::filesystem::path &path); /** * @brief Check if a process is a producer for a file. @@ -337,7 +344,7 @@ class Engine { * @param app_name Application name. * @return true if the process is a producer, false otherwise. */ - bool isProducer(const std::string &path, const std::string &app_name); + bool isProducer(const std::filesystem::path &path, const std::string &app_name); /** * @brief Check if a process is a consumer for a file. @@ -346,7 +353,7 @@ class Engine { * @param app_name Application name. * @return true if the process is a consumer, false otherwise. */ - bool isConsumer(const std::string &path, const std::string &app_name); + bool isConsumer(const std::filesystem::path &path, const std::string &app_name); /** * @brief Check if a file is firable. @@ -354,7 +361,7 @@ class Engine { * @param path File path. * @return true if the file is firable, false otherwise. */ - bool isFirable(const std::string &path); + bool isFirable(const std::filesystem::path &path); /** * @brief Check if a path refers to a file. @@ -362,7 +369,7 @@ class Engine { * @param path File path. * @return true if the path is a file, false otherwise. */ - bool isFile(const std::string &path); + bool isFile(const std::filesystem::path &path); /** * @brief Check if a path is excluded. @@ -370,7 +377,7 @@ class Engine { * @param path File path. * @return true if excluded, false otherwise. */ - bool isExcluded(const std::string &path) const; + bool isExcluded(const std::filesystem::path &path) const; /** * @brief Check if a path is a directory. @@ -378,7 +385,7 @@ class Engine { * @param path Directory path. * @return true if directory, false otherwise. */ - bool isDirectory(const std::string &path); + bool isDirectory(const std::filesystem::path &path); /** * @brief Check if a file is stored in memory. @@ -394,7 +401,7 @@ class Engine { * @param path * @return */ - bool isPermanent(const std::string &path); + bool isPermanent(const std::filesystem::path &path); }; /** diff --git a/src/Engine.cpp b/src/Engine.cpp index 81eca5f..9d24e78 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -1,9 +1,15 @@ #include "capiocl.hpp" #include -#include #include #include +#ifdef _WIN32 +#include +#define fnmatch(pattern, string, flags) (PathMatchSpecW(string, pattern) ? 0 : 1) +#else +#include +#endif + void capiocl::Engine::print() const { // First message print_message(CLI_LEVEL_JSON, ""); @@ -55,7 +61,7 @@ void capiocl::Engine::print() const { std::string color_preamble = std::get<10>(itm.second) ? "\033[38;5;034m" : "\033[38;5;172m"; std::string color_post = "\033[0m"; - std::string name_trunc = truncateLastN(itm.first, 12); + std::string name_trunc = truncateLastN(itm.first.string(), 12); auto kind = std::get<6>(itm.second) ? "F" : "D"; std::ostringstream base_line; @@ -136,10 +142,10 @@ bool capiocl::Engine::contains(const std::filesystem::path &file) { } size_t capiocl::Engine::size() const { return this->_locations.size(); } -void capiocl::Engine::add(std::string &path, std::vector &producers, +void capiocl::Engine::add(std::filesystem::path &path, std::vector &producers, std::vector &consumers, const std::string &commit_rule, const std::string &fire_rule, bool permanent, bool exclude, - const std::vector &dependencies) { + const std::vector &dependencies) { START_LOG(gettid(), "call(path=%s, commit=%s, fire=%s, permanent=%s, exclude=%s)", path.c_str(), commit_rule.c_str(), fire_rule.c_str(), permanent ? "YES" : "NO", exclude ? "YES" : "NO"); @@ -148,7 +154,7 @@ void capiocl::Engine::add(std::string &path, std::vector &producers permanent, exclude, true, 0, 0, dependencies, false)); } -void capiocl::Engine::newFile(const std::string &path) { +void capiocl::Engine::newFile(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (_locations.find(path) == _locations.end()) { std::string commit = COMMITTED_ON_TERMINATION; @@ -158,13 +164,13 @@ void capiocl::Engine::newFile(const std::string &path) { * Inherit commit and fire rules from LPM (Longest Prefix Match) directory * matchSize is used to compute LPM */ - std::string matchKey; + std::filesystem::path matchKey; size_t matchSize = 0; for (const auto &[filename, data] : _locations) { if (fnmatch(filename.c_str(), path.c_str(), FNM_PATHNAME) == 0 && - filename.length() > matchSize) { + filename.string().length() > matchSize) { LOG("Found match with %s", filename.c_str()); - matchSize = filename.length(); + matchSize = filename.string().length(); matchKey = filename; } } @@ -172,18 +178,18 @@ void capiocl::Engine::newFile(const std::string &path) { if (matchSize > 0) { LOG("Adding file %s to _locations with commit=%s, and fire=%s", path.c_str(), commit.c_str(), fire.c_str()); - const auto data = _locations.at(matchKey); - std::vector prod = std::get<0>(data); - std::vector cons = std::get<1>(data); - commit = std::get<2>(data); - fire = std::get<3>(data); - bool is_permanent = std::get<4>(data); - bool is_excluded = std::get<5>(data); - bool is_file = std::get<6>(data); - long committed_on_close_count = std::get<7>(data); - long expected_directory_file_count = std::get<8>(data); - std::vector file_deps = std::get<9>(data); - bool store_in_fs = std::get<10>(data); + const auto data = _locations.at(matchKey); + std::vector prod = std::get<0>(data); + std::vector cons = std::get<1>(data); + commit = std::get<2>(data); + fire = std::get<3>(data); + bool is_permanent = std::get<4>(data); + bool is_excluded = std::get<5>(data); + bool is_file = std::get<6>(data); + long committed_on_close_count = std::get<7>(data); + long expected_directory_file_count = std::get<8>(data); + std::vector file_deps = std::get<9>(data); + bool store_in_fs = std::get<10>(data); _locations.emplace(path, std::make_tuple(prod, cons, commit, fire, is_permanent, is_excluded, is_file, committed_on_close_count, expected_directory_file_count, file_deps, @@ -193,12 +199,12 @@ void capiocl::Engine::newFile(const std::string &path) { _locations.emplace( path, std::make_tuple(std::vector(), std::vector(), COMMITTED_ON_TERMINATION, MODE_UPDATE, false, false, true, 0, - 0, std::vector(), false)); + 0, std::vector(), false)); } } } -long capiocl::Engine::getDirectoryFileCount(const std::string &path) { +long capiocl::Engine::getDirectoryFileCount(const std::filesystem::path &path) { if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<8>(itm->second); } @@ -207,7 +213,7 @@ long capiocl::Engine::getDirectoryFileCount(const std::string &path) { return getDirectoryFileCount(path); } -void capiocl::Engine::addProducer(const std::string &path, std::string &producer) { +void capiocl::Engine::addProducer(const std::filesystem::path &path, std::string &producer) { START_LOG(gettid(), "call(path=%s, producer=%s)", path.c_str(), producer.c_str()); producer.erase(remove_if(producer.begin(), producer.end(), isspace), producer.end()); newFile(path); @@ -216,14 +222,15 @@ void capiocl::Engine::addProducer(const std::string &path, std::string &producer } } -void capiocl::Engine::addConsumer(const std::string &path, std::string &consumer) { +void capiocl::Engine::addConsumer(const std::filesystem::path &path, std::string &consumer) { START_LOG(gettid(), "call(path=%s, consumer=%s)", path.c_str(), consumer.c_str()); consumer.erase(remove_if(consumer.begin(), consumer.end(), isspace), consumer.end()); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<1>(itm->second).emplace_back(consumer); } } -void capiocl::Engine::addFileDependency(const std::string &path, std::string &file_dependency) { +void capiocl::Engine::addFileDependency(const std::filesystem::path &path, + std::string &file_dependency) { START_LOG(gettid(), "call(path=%s, consumer=%s)", path.c_str(), consumer.c_str()); file_dependency.erase(remove_if(file_dependency.begin(), file_dependency.end(), isspace), file_dependency.end()); @@ -232,14 +239,15 @@ void capiocl::Engine::addFileDependency(const std::string &path, std::string &fi } } -void capiocl::Engine::setCommitRule(const std::string &path, const std::string &commit_rule) { +void capiocl::Engine::setCommitRule(const std::filesystem::path &path, + const std::string &commit_rule) { START_LOG(gettid(), "call(path=%s, commit_rule=%s)", path.c_str(), commit_rule.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<2>(itm->second) = commit_rule; } } -std::string capiocl::Engine::getCommitRule(const std::string &path) { +std::string capiocl::Engine::getCommitRule(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { LOG("Commit rule: %s", std::get<2>(_locations.at(path)).c_str()); @@ -252,7 +260,7 @@ std::string capiocl::Engine::getCommitRule(const std::string &path) { return getCommitRule(path); } -std::string capiocl::Engine::getFireRule(const std::string &path) { +std::string capiocl::Engine::getFireRule(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { LOG("Fire rule: %s", std::get<3>(_locations.at(path)).c_str()); @@ -265,14 +273,14 @@ std::string capiocl::Engine::getFireRule(const std::string &path) { return getFireRule(path); } -void capiocl::Engine::setFireRule(const std::string &path, const std::string &fire_rule) { +void capiocl::Engine::setFireRule(const std::filesystem::path &path, const std::string &fire_rule) { START_LOG(gettid(), "call(path=%s, fire_rule=%s)", path.c_str(), fire_rule.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<3>(itm->second) = fire_rule; } } -bool capiocl::Engine::isFirable(const std::string &path) { +bool capiocl::Engine::isFirable(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(itm->second).c_str()); @@ -285,14 +293,14 @@ bool capiocl::Engine::isFirable(const std::string &path) { return std::get<3>(_locations.at((path))) == MODE_NO_UPDATE; } -void capiocl::Engine::setPermanent(const std::string &path, bool value) { +void capiocl::Engine::setPermanent(const std::filesystem::path &path, bool value) { START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<4>(itm->second) = value; } } -bool capiocl::Engine::isPermanent(const std::string &path) { +bool capiocl::Engine::isPermanent(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<4>(itm->second); @@ -302,28 +310,28 @@ bool capiocl::Engine::isPermanent(const std::string &path) { return isPermanent(path); } -void capiocl::Engine::setExclude(const std::string &path, const bool value) { +void capiocl::Engine::setExclude(const std::filesystem::path &path, const bool value) { START_LOG(gettid(), "call(path=%s, value=%s)", path.c_str(), value ? "true" : "false"); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<5>(itm->second) = value; } } -void capiocl::Engine::setDirectory(const std::string &path) { +void capiocl::Engine::setDirectory(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<6>(itm->second) = false; } } -void capiocl::Engine::setFile(const std::string &path) { +void capiocl::Engine::setFile(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<6>(itm->second) = true; } } -bool capiocl::Engine::isFile(const std::string &path) { +bool capiocl::Engine::isFile(const std::filesystem::path &path) { if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<6>(itm->second); } @@ -331,31 +339,31 @@ bool capiocl::Engine::isFile(const std::string &path) { return isPermanent(path); } -bool capiocl::Engine::isDirectory(const std::string &path) { +bool capiocl::Engine::isDirectory(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); return !isFile(path); } -void capiocl::Engine::setCommitedCloseNumber(const std::string &path, const long num) { +void capiocl::Engine::setCommitedCloseNumber(const std::filesystem::path &path, const long num) { START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<7>(itm->second) = num; } } -void capiocl::Engine::setDirectoryFileCount(const std::string &path, long num) { +void capiocl::Engine::setDirectoryFileCount(const std::filesystem::path &path, long num) { START_LOG(gettid(), "call(path=%s, num=%ld)", path.c_str(), num); if (const auto itm = _locations.find(path); itm != _locations.end()) { std::get<8>(itm->second) = num; } } -void capiocl::Engine::remove(const std::string &path) { +void capiocl::Engine::remove(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); _locations.erase(path); } -std::vector capiocl::Engine::getConsumers(const std::string &path) { +std::vector capiocl::Engine::getConsumers(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<1>(itm->second); @@ -363,7 +371,7 @@ std::vector capiocl::Engine::getConsumers(const std::string &path) return {}; } -bool capiocl::Engine::isConsumer(const std::string &path, const std::string &app_name) { +bool capiocl::Engine::isConsumer(const std::filesystem::path &path, const std::string &app_name) { START_LOG(gettid(), "call(path=%s, pid=%ld", path.c_str(), pid); LOG("App name is %s", app_name.c_str()); @@ -398,7 +406,7 @@ bool capiocl::Engine::isConsumer(const std::string &path, const std::string &app return false; } -std::vector capiocl::Engine::getProducers(const std::string &path) { +std::vector capiocl::Engine::getProducers(const std::filesystem::path &path) { START_LOG(gettid(), "call(path=%s)", path.c_str()); if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<0>(itm->second); @@ -406,7 +414,7 @@ std::vector capiocl::Engine::getProducers(const std::string &path) return {}; } -bool capiocl::Engine::isProducer(const std::string &path, const std::string &app_name) { +bool capiocl::Engine::isProducer(const std::filesystem::path &path, const std::string &app_name) { START_LOG(gettid(), "call(path=%s, pid=%ld", path.c_str(), pid); LOG("App name is %s", app_name.c_str()); @@ -442,7 +450,7 @@ bool capiocl::Engine::isProducer(const std::string &path, const std::string &app } void capiocl::Engine::setFileDeps(const std::filesystem::path &path, - const std::vector &dependencies) { + const std::vector &dependencies) { START_LOG(gettid(), "call()"); if (dependencies.empty()) { return; @@ -467,7 +475,7 @@ long capiocl::Engine::getCommitCloseCount(std::filesystem::path::iterator::refer return count; }; -std::vector +std::vector capiocl::Engine::getCommitOnFileDependencies(const std::filesystem::path &path) { if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<9>(itm->second); @@ -497,9 +505,9 @@ bool capiocl::Engine::isStoredInMemory(const std::filesystem::path &path) { return false; } -std::vector capiocl::Engine::getFileToStoreInMemory() { +std::vector capiocl::Engine::getFileToStoreInMemory() { START_LOG(gettid(), "call()"); - std::vector files; + std::vector files; for (const auto &[path, file] : _locations) { if (std::get<10>(file)) { @@ -510,7 +518,7 @@ std::vector capiocl::Engine::getFileToStoreInMemory() { return files; } -std::string capiocl::Engine::getHomeNode(const std::string &path) { +std::string capiocl::Engine::getHomeNode(const std::filesystem::path &path) { // TODO: understand here how to get the home node policy when home_node_policies are // being implemented. START_LOG(gettid(), "call(path=%s)", path.c_str()); @@ -523,7 +531,7 @@ std::string capiocl::Engine::getHomeNode(const std::string &path) { return node_name; } -bool capiocl::Engine::isExcluded(const std::string &path) const { +bool capiocl::Engine::isExcluded(const std::filesystem::path &path) const { if (const auto itm = _locations.find(path); itm != _locations.end()) { return std::get<5>(itm->second); @@ -535,8 +543,8 @@ bool capiocl::Engine::isExcluded(const std::string &path) const { for (const auto &[glob_path, entry] : _locations) { if (fnmatch(glob_path.c_str(), path.c_str(), FNM_PATHNAME) == 0) { LOG("Found match with %s", glob_path.c_str()); - if (glob_path.length() > lpm_match_size) { - lpm_match_size = glob_path.length(); + if (glob_path.string().length() > lpm_match_size) { + lpm_match_size = glob_path.string().length(); lpm_match = std::get<5>(entry); LOG("Match is longer than previous match. storing value = %s", lpm_match ? "true" : "false"); diff --git a/src/Parser.cpp b/src/Parser.cpp index 28d3679..e0b084a 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -94,7 +94,7 @@ capiocl::Parser::parse(const std::filesystem::path &source, "Path : " + file_path.string() + " IS RELATIVE! resolving..."); file_path = resolve_prefix / file_path; } - locations->newFile(file_path.c_str()); + locations->newFile(file_path); locations->addConsumer(file_path, app_name); } @@ -121,7 +121,7 @@ capiocl::Parser::parse(const std::filesystem::path &source, for (const auto &stream_item : app["streaming"]) { bool is_file = true; std::vector streaming_names; - std::vector file_deps; + std::vector file_deps; std::string commit_rule = COMMITTED_ON_TERMINATION, mode = MODE_UPDATE; long int n_close = -1; int64_t n_files = -1; diff --git a/tests/cpp/main.cpp b/tests/cpp/main.cpp index ee571fe..ac292d7 100644 --- a/tests/cpp/main.cpp +++ b/tests/cpp/main.cpp @@ -60,8 +60,9 @@ TEST(testCapioClEngine, testAddFileDefaultGlobQuestion) { TEST(testCapioClEngine, testAddFileManually) { capiocl::Engine engine; EXPECT_EQ(engine.size(), 0); - std::string path = "test.dat"; - std::vector producers, consumers, file_dependencies; + std::filesystem::path path = "test.dat"; + std::vector producers, consumers; + std::vector file_dependencies; engine.add(path, producers, consumers, capiocl::COMMITTED_ON_TERMINATION, capiocl::MODE_UPDATE, false, false, file_dependencies); @@ -81,8 +82,9 @@ TEST(testCapioClEngine, testAddFileManually) { TEST(testCapioClEngine, testAddFileManuallyGlob) { capiocl::Engine engine; EXPECT_EQ(engine.size(), 0); - std::string path = "test.*"; - std::vector producers, consumers, file_dependencies; + std::filesystem::path path = "test.*"; + std::vector producers, consumers; + std::vector file_dependencies; engine.add(path, producers, consumers, capiocl::COMMITTED_ON_TERMINATION, capiocl::MODE_UPDATE, false, false, file_dependencies); @@ -102,8 +104,9 @@ TEST(testCapioClEngine, testAddFileManuallyGlob) { TEST(testCapioClEngine, testAddFileManuallyQuestion) { capiocl::Engine engine; EXPECT_EQ(engine.size(), 0); - std::string path = "test.?"; - std::vector producers, consumers, file_dependencies; + std::filesystem::path path = "test.?"; + std::vector producers, consumers; + std::vector file_dependencies; engine.add(path, producers, consumers, capiocl::COMMITTED_ON_CLOSE, capiocl::MODE_NO_UPDATE, false, false, file_dependencies); @@ -133,8 +136,9 @@ TEST(testCapioClEngine, testAddFileManuallyQuestion) { TEST(testCapioClEngine, testAddFileManuallyGlobExplcit) { capiocl::Engine engine; EXPECT_EQ(engine.size(), 0); - std::string path = "test.[abc][abc][abc]"; - std::vector producers, consumers, file_dependencies; + std::filesystem::path path = "test.[abc][abc][abc]"; + std::vector producers, consumers; + std::vector file_dependencies; engine.add(path, producers, consumers, capiocl::COMMITTED_ON_CLOSE, capiocl::MODE_NO_UPDATE, false, false, file_dependencies); diff --git a/tests/python/test_engine.py b/tests/python/test_engine.py index dab0f94..5561a55 100644 --- a/tests/python/test_engine.py +++ b/tests/python/test_engine.py @@ -1,24 +1,9 @@ -''' -TEST(testpy_capio_clEngine, testAddFileDefault) { - py_capio_cl::Engine engine; -EXPECT_EQ(engine.size(), 0); -engine.newFile("test.dat"); -EXPECT_EQ(engine.size(), 1); -EXPECT_EQ(engine.getCommitRule("test.dat"), py_capio_cl::COMMITTED_ON_TERMINATION); -EXPECT_EQ(engine.getFireRule("test.dat"), py_capio_cl::MODE_UPDATE); -EXPECT_TRUE(engine.getConsumers("test.dat").empty()); -EXPECT_TRUE(engine.getProducers("test.dat").empty()); -EXPECT_FALSE(engine.isPermanent("test.dat")); -EXPECT_FALSE(engine.isExcluded("test.dat")); -EXPECT_TRUE(engine.isFile("test.dat")); -EXPECT_FALSE(engine.isDirectory("test.dat")); -EXPECT_EQ(engine.getDirectoryFileCount("test.dat"), 0); -EXPECT_FALSE(engine.isStoredInMemory("test.dat")); -} -''' - import os import importlib.util +from pathlib import PosixPath + +if not os.path.exists(os.getenv("CAPIO_CL_PY_BINDING_PATH")): + raise FileNotFoundError(os.getenv("CAPIO_CL_PY_BINDING_PATH")) spec = importlib.util.spec_from_file_location("py_capio_cl", os.getenv("CAPIO_CL_PY_BINDING_PATH")) py_capio_cl = importlib.util.module_from_spec(spec) @@ -211,10 +196,10 @@ def test_producers_consumers_file_dependencies(): assert engine.getCommitOnFileDependencies("test.dat") == [] engine.addFileDependency("test.dat", file_dependencies[0]) assert len(engine.getCommitOnFileDependencies("test.dat")) == 1 - assert engine.getCommitOnFileDependencies("test.dat")[0] == file_dependencies[0] + assert engine.getCommitOnFileDependencies("test.dat")[0] == PosixPath(file_dependencies[0]) engine.addFileDependency("test.dat", file_dependencies[1]) assert len(engine.getCommitOnFileDependencies("test.dat")) == 2 - assert engine.getCommitOnFileDependencies("test.dat")[1] == file_dependencies[1] + assert engine.getCommitOnFileDependencies("test.dat")[1] == PosixPath(file_dependencies[1]) def test_producers_consumers_file_dependencies_glob(): @@ -245,7 +230,7 @@ def test_producers_consumers_file_dependencies_glob(): assert engine.getCommitOnFileDependencies("test.dat") == [] engine.addFileDependency("test.dat", file_dependencies[0]) assert len(engine.getCommitOnFileDependencies("test.dat")) == 1 - assert engine.getCommitOnFileDependencies("test.dat")[0] == file_dependencies[0] + assert engine.getCommitOnFileDependencies("test.dat")[0] == PosixPath(file_dependencies[0]) engine.addFileDependency("test.dat", file_dependencies[1]) assert len(engine.getCommitOnFileDependencies("test.dat")) == 2 - assert engine.getCommitOnFileDependencies("test.dat")[1] == file_dependencies[1] \ No newline at end of file + assert engine.getCommitOnFileDependencies("test.dat")[1] == PosixPath(file_dependencies[1]) \ No newline at end of file