Implement FileMonitor
authorChanggyu Choi <changyu.choi@samsung.com>
Fri, 11 Apr 2025 01:52:15 +0000 (10:52 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Wed, 14 May 2025 09:02:19 +0000 (18:02 +0900)
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
src/activation_method/file_monitor.cc
src/activation_method/file_monitor.hh

index 82656e0cd6a0823b729907919316a5d9422e42f1..4d34cb1c50e3943db252ad791382668f4d806c58 100644 (file)
@@ -1,12 +1,91 @@
 #include "file_monitor.hh"
 
-tizen_base::FileMonitor::FileMonitor(std::string name,
-                                     std::string path,
-                                     IEventListener* listener) {}
+#include <system_error>
 
-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<FileMonitor*>(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<FileMonitor*>(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<FileMonitor*>(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
index 797c118f5e1bcfb40bd7032cb316b5b0bbcfbd6b..e82929e41f0ac2620d8b8b04f5b6bc81c0b3d416 100644 (file)
 #ifndef ACTIVATION_METHOD_FILE_MONITOR_HH_
 #define ACTIVATION_METHOD_FILE_MONITOR_HH_
 
-#include <glib.h>
 #include <gio/gio.h>
+#include <glib.h>
 
+#include <filesystem>
 #include <string>
 
-#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_