From fbdc88e769e65e29264e547a51dea279fb343a9f Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Fri, 11 Apr 2025 10:52:15 +0900 Subject: [PATCH] Implement FileMonitor Signed-off-by: Changgyu Choi --- src/activation_method/file_monitor.cc | 95 ++++++++++++++++++++++++--- src/activation_method/file_monitor.hh | 27 ++++++-- 2 files changed, 110 insertions(+), 12 deletions(-) diff --git a/src/activation_method/file_monitor.cc b/src/activation_method/file_monitor.cc index 82656e0..4d34cb1 100644 --- a/src/activation_method/file_monitor.cc +++ b/src/activation_method/file_monitor.cc @@ -1,12 +1,91 @@ #include "file_monitor.hh" -tizen_base::FileMonitor::FileMonitor(std::string name, - std::string path, - IEventListener* listener) {} +#include -gboolean tizen_base::FileMonitor::UnixFdSourceFunc(gint fd, - GIOCondition cond, - gpointer data) { - // TODO - return FALSE; +#include "../log_private.hh" + +namespace tizen_base { + +FileMonitor::FileMonitor(std::string name, + std::string path, + IEventListener* listener) + : name_(std::move(name)), listener_(listener) { + fs::path full_path = fs::path(path); + std::error_code error; + if (fs::exists(full_path, error)) { + _W("[%s] already exists", full_path.string().c_str()); + g_idle_add( + +[](gpointer data) -> gboolean { + auto* self = static_cast(data); + self->NotifyEvent(); + return G_SOURCE_REMOVE; + }, + this); + return; + } + + listener_ = listener; + dir_path_ = full_path.parent_path(); + file_name_ = full_path.filename().string(); + dir_ = g_file_new_for_path(dir_path_.c_str()); + monitor_ = + g_file_monitor_directory(dir_, G_FILE_MONITOR_NONE, nullptr, nullptr); + + if (monitor_ == nullptr) { + g_object_unref(dir_); + dir_ = nullptr; + std::runtime_error("Failed to create monitor"); + } + + g_signal_connect(monitor_, "changed", G_CALLBACK(OnFileChanged), this); + if (fs::exists(full_path, error)) { + if (monitor_) + g_object_unref(monitor_); + + if (dir_) + g_object_unref(dir_); + + g_idle_add( + +[](gpointer data) -> gboolean { + auto* self = static_cast(data); + self->NotifyEvent(); + return G_SOURCE_REMOVE; + }, + this); + } +} + +FileMonitor::~FileMonitor() { + if (monitor_) + g_object_unref(monitor_); + + if (dir_) + g_object_unref(dir_); } + +gboolean FileMonitor::OnFileChanged(GFileMonitor* monitor, + GFile* file, + GFile* other_file, + GFileMonitorEvent event_type, + gpointer user_data) { + auto* self = static_cast(user_data); + const auto& file_name = self->file_name_; + gchar* basename = g_file_get_basename(file); + + if (event_type == G_FILE_MONITOR_EVENT_CREATED && + strcmp(basename, file_name.c_str()) == 0) { + _I("[%s] created", basename); + self->NotifyEvent(); + + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +void FileMonitor::NotifyEvent() { + if (listener_) + listener_->OnEvent(name_); +} + +} // namespace tizen_base diff --git a/src/activation_method/file_monitor.hh b/src/activation_method/file_monitor.hh index 797c118..e82929e 100644 --- a/src/activation_method/file_monitor.hh +++ b/src/activation_method/file_monitor.hh @@ -17,22 +17,41 @@ #ifndef ACTIVATION_METHOD_FILE_MONITOR_HH_ #define ACTIVATION_METHOD_FILE_MONITOR_HH_ -#include #include +#include +#include #include -#include "event_listener.hh" +#include "../event_listener.hh" namespace tizen_base { +namespace fs = std::filesystem; + class FileMonitor { public: FileMonitor(std::string name, std::string path, IEventListener* listener); - static gboolean UnixFdSourceFunc(gint fd, GIOCondition cond, gpointer data); -}; + ~FileMonitor(); + private: + static gboolean OnFileChanged(GFileMonitor* monitor, + GFile* file, + GFile* other_file, + GFileMonitorEvent event_type, + gpointer user_data); + + void NotifyEvent(); + + GFileMonitor* monitor_ = nullptr; + GFile* dir_ = nullptr; + std::string name_; + fs::path dir_path_; + std::string file_name_; + IEventListener* listener_; }; +}; // namespace tizen_base + #endif // ACTIVATION_METHOD_FILE_MONITOR_HH_ -- 2.34.1