diff options
author | Adriana Kobylak <anoo@us.ibm.com> | 2018-04-24 11:37:21 -0500 |
---|---|---|
committer | Adriana Kobylak <anoo@us.ibm.com> | 2018-05-08 11:51:36 -0500 |
commit | b072d1bec4f8c5ee2de13722a4af63ba4350d7c7 (patch) | |
tree | 86d93a28745daacd5518c1888e82f9879cfcdf96 | |
parent | 7e8d76b3de932520789a8fb2920cd4b6fde9d388 (diff) | |
download | phosphor-bmc-code-mgmt-b072d1bec4f8c5ee2de13722a4af63ba4350d7c7.tar.gz phosphor-bmc-code-mgmt-b072d1bec4f8c5ee2de13722a4af63ba4350d7c7.zip |
sync_manager: Create sync watch class
Create a watch class to monitor the files and directories
specified in the synclist file.
Store the file descriptors and file names in a map to be
able to know the full path of the file that triggered the
event. The watch descriptor number does not change so it
can be a single variable.
Change-Id: I211225ddc012af85d9be39ae5d40b8258d73435d
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
-rwxr-xr-x | Makefile.am | 9 | ||||
-rwxr-xr-x | configure.ac | 8 | ||||
-rw-r--r-- | sync_manager.cpp | 17 | ||||
-rw-r--r-- | sync_manager.hpp | 6 | ||||
-rw-r--r-- | sync_manager_main.cpp | 30 | ||||
-rw-r--r-- | sync_watch.cpp | 89 | ||||
-rw-r--r-- | sync_watch.hpp | 66 |
7 files changed, 221 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am index b4755c5..9b6b508 100755 --- a/Makefile.am +++ b/Makefile.am @@ -45,9 +45,14 @@ phosphor_image_updater_SOURCES += image_verify.cpp endif if WANT_SYNC -noinst_HEADERS += sync_manager.hpp +noinst_HEADERS += \ + sync_manager.hpp \ + sync_watch.hpp sbin_PROGRAMS += phosphor-sync-software-manager -phosphor_sync_software_manager_SOURCES = sync_manager_main.cpp +phosphor_sync_software_manager_SOURCES = \ + sync_manager.cpp \ + sync_watch.cpp \ + sync_manager_main.cpp phosphor_sync_software_manager_CXXFLAGS = $(generic_cxxflags) phosphor_sync_software_manager_LDFLAGS = $(generic_ldflags) endif diff --git a/configure.ac b/configure.ac index 65afe9a..1155cfe 100755 --- a/configure.ac +++ b/configure.ac @@ -109,6 +109,14 @@ AC_ARG_VAR(IMG_UPLOAD_DIR, [Directory where downloaded software images are place AS_IF([test "x$IMG_UPLOAD_DIR" == "x"], [IMG_UPLOAD_DIR="/tmp/images"]) AC_DEFINE_UNQUOTED([IMG_UPLOAD_DIR], ["$IMG_UPLOAD_DIR"], [Directory where downloaded software images are placed]) +AC_ARG_VAR(SYNC_LIST_FILE_NAME, [The name of the sync list file]) +AS_IF([test "x$SYNC_LIST_FILE_NAME" == "x"], [SYNC_LIST_FILE_NAME="synclist"]) +AC_DEFINE_UNQUOTED([SYNC_LIST_FILE_NAME], ["$SYNC_LIST_FILE_NAME"], [The name of the sync list file]) + +AC_ARG_VAR(SYNC_LIST_DIR_PATH, [The path to the sync list file directory]) +AS_IF([test "x$SYNC_LIST_DIR_PATH" == "x"], [SYNC_LIST_DIR_PATH="/etc/"]) +AC_DEFINE_UNQUOTED([SYNC_LIST_DIR_PATH], ["$SYNC_LIST_DIR_PATH"], [The path to the sync list file directory]) + AC_ARG_VAR(MANIFEST_FILE_NAME, [The name of the MANIFEST file]) AS_IF([test "x$MANIFEST_FILE_NAME" == "x"], [MANIFEST_FILE_NAME="MANIFEST"]) AC_DEFINE_UNQUOTED([MANIFEST_FILE_NAME], ["$MANIFEST_FILE_NAME"], [The name of the MANIFEST file]) diff --git a/sync_manager.cpp b/sync_manager.cpp new file mode 100644 index 0000000..6a50711 --- /dev/null +++ b/sync_manager.cpp @@ -0,0 +1,17 @@ +#include "sync_manager.hpp" + +namespace phosphor +{ +namespace software +{ +namespace manager +{ + +int Sync::processEntry() +{ + return 0; +} + +} // namespace manager +} // namespace software +} // namepsace phosphor diff --git a/sync_manager.hpp b/sync_manager.hpp index a48a806..a940461 100644 --- a/sync_manager.hpp +++ b/sync_manager.hpp @@ -21,6 +21,12 @@ class Sync Sync(Sync&&) = default; Sync& operator=(Sync&&) = default; ~Sync() = default; + + /** + * @brief Process requested file or directory. + * @param[out] result - 0 if successful. + */ + int processEntry(); }; } // namespace manager diff --git a/sync_manager_main.cpp b/sync_manager_main.cpp index 09aea5c..46a2d95 100644 --- a/sync_manager_main.cpp +++ b/sync_manager_main.cpp @@ -1,15 +1,41 @@ +#include <exception> +#include <phosphor-logging/log.hpp> #include <sdbusplus/bus.hpp> #include <sdbusplus/server/manager.hpp> +#include <systemd/sd-event.h> #include "config.h" #include "sync_manager.hpp" +#include "sync_watch.hpp" int main(int argc, char* argv[]) { auto bus = sdbusplus::bus::new_default(); + sd_event* loop = nullptr; + sd_event_default(&loop); + sdbusplus::server::manager::manager objManager(bus, SOFTWARE_OBJPATH); - phosphor::software::manager::Sync syncManager(); - bus.request_name(SYNC_BUSNAME); + + try + { + phosphor::software::manager::Sync syncManager; + bus.request_name(SYNC_BUSNAME); + + using namespace phosphor::software::manager; + phosphor::software::manager::SyncWatch watch( + *loop, std::bind(std::mem_fn(&Sync::processEntry), &syncManager)); + bus.attach_event(loop, SD_EVENT_PRIORITY_NORMAL); + sd_event_loop(loop); + } + catch (std::exception& e) + { + using namespace phosphor::logging; + log<level::ERR>(e.what()); + sd_event_unref(loop); + return -1; + } + + sd_event_unref(loop); return 0; } diff --git a/sync_watch.cpp b/sync_watch.cpp new file mode 100644 index 0000000..0fc61d8 --- /dev/null +++ b/sync_watch.cpp @@ -0,0 +1,89 @@ +#include <experimental/filesystem> +#include <fstream> +#include <phosphor-logging/log.hpp> +#include <sys/inotify.h> +#include <unistd.h> +#include "config.h" +#include "sync_watch.hpp" + +namespace phosphor +{ +namespace software +{ +namespace manager +{ + +using namespace phosphor::logging; +namespace fs = std::experimental::filesystem; + +SyncWatch::SyncWatch(sd_event& loop, + std::function<int(fs::path&)> syncCallback) : + syncCallback(syncCallback) +{ + auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME; + if (fs::exists(syncfile)) + { + std::string line; + std::ifstream file(syncfile.c_str()); + while (std::getline(file, line)) + { + auto fd = inotify_init1(IN_NONBLOCK); + if (-1 == fd) + { + log<level::ERR>("inotify_init1 failed", + entry("ERRNO=%d", errno), + entry("FILENAME=%s", line.c_str()), + entry("SYNCFILE=%s", syncfile.c_str())); + continue; + } + + auto wd = inotify_add_watch(fd, line.c_str(), IN_CLOSE_WRITE); + if (-1 == wd) + { + log<level::ERR>("inotify_add_watch failed", + entry("ERRNO=%d", errno), + entry("FILENAME=%s", line.c_str()), + entry("SYNCFILE=%s", syncfile.c_str())); + close(fd); + continue; + } + + auto rc = + sd_event_add_io(&loop, nullptr, fd, EPOLLIN, callback, this); + if (0 > rc) + { + log<level::ERR>("failed to add to event loop", + entry("RC=%d", rc), + entry("FILENAME=%s", line.c_str()), + entry("SYNCFILE=%s", syncfile.c_str())); + inotify_rm_watch(fd, wd); + close(fd); + continue; + } + + fileMap[fd].insert(std::make_pair(wd, fs::path(line))); + } + } +} + +SyncWatch::~SyncWatch() +{ + for (const auto& fd : fileMap) + { + for (const auto& wd : fd.second) + { + inotify_rm_watch(fd.first, wd.first); + } + close(fd.first); + } +} + +int SyncWatch::callback(sd_event_source* s, int fd, uint32_t revents, + void* userdata) +{ + return 0; +} + +} // namespace manager +} // namespace software +} // namespace phosphor diff --git a/sync_watch.hpp b/sync_watch.hpp new file mode 100644 index 0000000..a7f8557 --- /dev/null +++ b/sync_watch.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <experimental/filesystem> +#include <functional> +#include <systemd/sd-event.h> + +namespace phosphor +{ +namespace software +{ +namespace manager +{ + +namespace fs = std::experimental::filesystem; + +/** @class SyncWatch + * + * @brief Adds inotify watch on persistent files to be synced + * + * The inotify watch is hooked up with sd-event, so that on call back, + * appropriate actions related to syncing files can be taken. + */ +class SyncWatch +{ + public: + /** @brief ctor - hook inotify watch with sd-event + * + * @param[in] loop - sd-event object + * @param[in] syncCallback - The callback function for processing + * files + */ + SyncWatch(sd_event& loop, std::function<int(fs::path&)> syncCallback); + + SyncWatch(const SyncWatch&) = delete; + SyncWatch& operator=(const SyncWatch&) = delete; + SyncWatch(SyncWatch&&) = default; + SyncWatch& operator=(SyncWatch&&) = default; + + /** @brief dtor - remove inotify watch and close fd's + */ + ~SyncWatch(); + + private: + /** @brief sd-event callback + * + * @param[in] s - event source, floating (unused) in our case + * @param[in] fd - inotify fd + * @param[in] revents - events that matched for fd + * @param[in] userdata - pointer to SyncWatch object + * @returns 0 on success, -1 on fail + */ + static int callback(sd_event_source* s, int fd, uint32_t revents, + void* userdata); + + /** @brief Map of file descriptors, watch descriptors, and file paths */ + using fd = int; + using wd = int; + std::map<fd, std::map<wd, fs::path>> fileMap; + + /** @brief The callback function for processing the inotify event */ + std::function<int(fs::path&)> syncCallback; +}; + +} // namespace manager +} // namespace software +} // namespace phosphor |