[tracker-miners/wip/carlosg/fix-monitor-race-condition: 1/2] libtracker-miner: Refactor TrackerMonitor event tracking




commit 9ef12ee9f314340bc18dce598be8f77c47e24946
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sat Aug 1 14:06:46 2020 +0200

    libtracker-miner: Refactor TrackerMonitor event tracking
    
    Make it cache more information about the individual events, this
    will be useful for events that we don't flush while handling events
    (eg. a timeout instead of CHANGES_DONE_HINT).

 src/libtracker-miner/tracker-monitor.c | 72 +++++++++++++++++++++-------------
 1 file changed, 44 insertions(+), 28 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-monitor.c b/src/libtracker-miner/tracker-monitor.c
index cf5d6c7c1..2aa495c6f 100644
--- a/src/libtracker-miner/tracker-monitor.c
+++ b/src/libtracker-miner/tracker-monitor.c
@@ -34,9 +34,6 @@
 
 #include "libtracker-miners-common/tracker-debug.h"
 
-/* The life time of an item in the cache */
-#define CACHE_LIFETIME_SECONDS 1
-
 typedef struct TrackerMonitorPrivate  TrackerMonitorPrivate;
 
 struct TrackerMonitorPrivate {
@@ -68,6 +65,13 @@ typedef struct {
        gboolean  expirable;
 } EventData;
 
+typedef struct {
+       TrackerMonitor *monitor;
+       GFile *file;
+       gboolean is_directory;
+       GFileMonitorEvent event_type;
+} CachedEvent;
+
 enum {
        ITEM_CREATED,
        ITEM_UPDATED,
@@ -188,6 +192,13 @@ tracker_monitor_class_init (TrackerMonitorClass *klass)
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
 }
 
+static void
+cached_event_free (CachedEvent *event)
+{
+       g_object_unref (event->file);
+       g_free (event);
+}
+
 static void
 tracker_monitor_init (TrackerMonitor *object)
 {
@@ -212,7 +223,7 @@ tracker_monitor_init (TrackerMonitor *object)
                g_hash_table_new_full (g_file_hash,
                                       (GEqualFunc) g_file_equal,
                                       g_object_unref,
-                                      NULL);
+                                      (GDestroyNotify) cached_event_free);
 
        /* For the first monitor we get the type and find out if we
         * are using inotify, FAM, polling, etc.
@@ -611,41 +622,46 @@ emit_signal_for_event (TrackerMonitor    *monitor,
 }
 
 static void
-flush_cached_event (TrackerMonitor *monitor,
-                    GFile          *file,
-                    gboolean        is_directory)
+flush_event_now (TrackerMonitor *monitor,
+                 GFile          *file)
 {
-       gpointer value = NULL;
        TrackerMonitorPrivate *priv;
+       CachedEvent *event;
 
        priv = tracker_monitor_get_instance_private (monitor);
 
-       if (g_hash_table_lookup_extended (priv->cached_events,
-                                         file, NULL, &value)) {
-               GFileMonitorEvent prev_event_type = GPOINTER_TO_UINT (value);
+       event = g_hash_table_lookup (priv->cached_events, file);
 
+       if (event) {
+               emit_signal_for_event (monitor, event->event_type,
+                                      event->is_directory, event->file, NULL);
                g_hash_table_remove (priv->cached_events, file);
-               emit_signal_for_event (monitor, prev_event_type,
-                                      is_directory, file, NULL);
        }
 }
 
 static void
 cache_event (TrackerMonitor    *monitor,
              GFile             *file,
-             GFileMonitorEvent  event_type)
+             GFileMonitorEvent  event_type,
+             gboolean           is_directory)
 {
        TrackerMonitorPrivate *priv;
+       CachedEvent *event;
 
        priv = tracker_monitor_get_instance_private (monitor);
-
-       if (g_hash_table_lookup_extended (priv->cached_events, file,
-                                         NULL, NULL))
-               return;
-
-       g_hash_table_insert (priv->cached_events,
-                            g_object_ref (file),
-                            GUINT_TO_POINTER (event_type));
+       event = g_hash_table_lookup (priv->cached_events, file);
+
+       if (!event) {
+               event = g_new0 (CachedEvent, 1);
+               event->monitor = monitor;
+               event->file = g_object_ref (file);
+               event->event_type = event_type;
+               event->is_directory = is_directory;
+
+               g_hash_table_insert (priv->cached_events,
+                                    g_object_ref (file),
+                                    event);
+       }
 }
 
 static void
@@ -660,10 +676,11 @@ monitor_event_cb (GFileMonitor      *file_monitor,
        gchar *other_file_uri;
        gboolean is_directory = FALSE;
        TrackerMonitorPrivate *priv;
-       gpointer value;
+       CachedEvent *prev_event;
 
        monitor = user_data;
        priv = tracker_monitor_get_instance_private (monitor);
+       prev_event = g_hash_table_lookup (priv->cached_events, file);
 
        if (G_UNLIKELY (!priv->enabled)) {
                TRACKER_NOTE (MONITORS, g_message ("Silently dropping monitor event, monitor disabled for 
now"));
@@ -704,16 +721,15 @@ monitor_event_cb (GFileMonitor      *file_monitor,
        case G_FILE_MONITOR_EVENT_CREATED:
        case G_FILE_MONITOR_EVENT_CHANGED:
                if (!priv->use_changed_event) {
-                       cache_event (monitor, file, event_type);
+                       cache_event (monitor, file, event_type, is_directory);
                } else {
                        emit_signal_for_event (monitor, event_type,
                                               is_directory, file, NULL);
                }
                break;
        case G_FILE_MONITOR_EVENT_DELETED:
-               if (g_hash_table_lookup_extended (priv->cached_events,
-                                                 file, NULL, &value) &&
-                   GPOINTER_TO_UINT (value) == G_FILE_MONITOR_EVENT_CREATED) {
+               if (prev_event &&
+                   prev_event->event_type == G_FILE_MONITOR_EVENT_CREATED) {
                        /* Consume both the cached CREATED event and this one */
                        g_hash_table_remove (priv->cached_events, file);
                        break;
@@ -728,7 +744,7 @@ monitor_event_cb (GFileMonitor      *file_monitor,
                                       is_directory, file, NULL);
                break;
        case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
-               flush_cached_event (monitor, file, is_directory);
+               flush_event_now (monitor, file);
                break;
        case G_FILE_MONITOR_EVENT_MOVED_IN:
                if (other_file) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]