[gnome-logs/wip/larsu/listmodel: 17/22] Turn journal iteration logic inside out



commit b3ab13985479d55ea6965a70f14b4b2c788e3604
Author: Lars Uebernickel <lars uebernic de>
Date:   Sat Feb 14 19:42:24 2015 +0100

    Turn journal iteration logic inside out
    
    Instead of fetching all journal entries and then adding widgets in an
    idle, fetch journal entries in the idle just before creating the
    corresponding widget.
    
    gl_journal_query() is replaced by gl_journal_previous(), which returns
    the previous entry.
    
    This makes switching between pages much more responsive.

 src/gl-eventviewlist.c |   98 +++++++-----------------------
 src/gl-journal.c       |  154 +++++++++++++++++------------------------------
 src/gl-journal.h       |    4 +-
 3 files changed, 80 insertions(+), 176 deletions(-)
---
diff --git a/src/gl-eventviewlist.c b/src/gl-eventviewlist.c
index da228ad..110afd8 100644
--- a/src/gl-eventviewlist.c
+++ b/src/gl-eventviewlist.c
@@ -44,14 +44,12 @@ typedef struct
     gchar *search_text;
 
     GlEventViewRowStyle current_row_style;
-    GQueue *pending_results;
-    GList *results;
     guint insert_idle_id;
 } GlEventViewListPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GlEventViewList, gl_event_view_list, GTK_TYPE_BOX)
 
-static const gssize N_RESULTS_IDLE = 25;
+static const gssize N_RESULTS_IDLE = 5;
 static const gchar DESKTOP_SCHEMA[] = "org.gnome.desktop.interface";
 static const gchar SETTINGS_SCHEMA[] = "org.gnome.Logs";
 static const gchar CLOCK_FORMAT[] = "clock-format";
@@ -308,85 +306,36 @@ gl_event_view_list_box_new (GlEventViewList *view)
 }
 
 static gboolean
-insert_idle (GlEventViewList *view)
+insert_idle (gpointer data)
 {
-    GlEventViewListPrivate *priv;
-
-    priv = gl_event_view_list_get_instance_private (view);
+    GlEventViewList *view = data;
+    GlEventViewListPrivate *priv = gl_event_view_list_get_instance_private (view);
+    gint i;
 
-    if (priv->pending_results)
+    for (i = 0; i < N_RESULTS_IDLE; i++)
     {
-        gssize i;
+        GlJournalResult *result;
+        GtkWidget *row;
 
-        for (i = 0; i < N_RESULTS_IDLE; i++)
+        result = gl_journal_previous (priv->journal);
+        if (result)
         {
-            GlJournalResult *result;
-            GtkWidget *row;
-
-            result = g_queue_pop_head (priv->pending_results);
-
-            if (result)
-            {
-                row = gl_event_view_row_new (result,
-                                             priv->current_row_style,
-                                             priv->clock_format);
-                gtk_container_add (GTK_CONTAINER (priv->active_listbox), row);
-                gtk_widget_show_all (row);
-            }
-            else
-            {
-                g_queue_free (priv->pending_results);
-                gl_journal_results_free (priv->results);
-                priv->pending_results = NULL;
-                priv->results = NULL;
+            row = gl_event_view_row_new (result,
+                                         priv->current_row_style,
+                                         priv->clock_format);
+            gtk_container_add (GTK_CONTAINER (priv->active_listbox), row);
+            gtk_widget_show_all (row);
 
-                priv->insert_idle_id = 0;
-                return G_SOURCE_REMOVE;
-            }
+            gl_journal_result_unref (result);
+        }
+        else
+        {
+            priv->insert_idle_id = 0;
+            return G_SOURCE_REMOVE;
         }
-
-        return G_SOURCE_CONTINUE;
-    }
-    else
-    {
-        priv->insert_idle_id = 0;
-        return G_SOURCE_REMOVE;
-    }
-}
-
-static void
-query_ready (GObject *source_object,
-             GAsyncResult *res,
-             gpointer user_data)
-{
-    GlEventViewList *view;
-    GlEventViewListPrivate *priv;
-    GlJournal *journal;
-    GError *error = NULL;
-    GList *l;
-
-    view = GL_EVENT_VIEW_LIST (user_data);
-    priv = gl_event_view_list_get_instance_private (view);
-    journal = GL_JOURNAL (source_object);
-
-    priv->results = gl_journal_query_finish (journal, res, &error);
-
-    if (!priv->results)
-    {
-        /* TODO: Check for error. */
-        g_error_free (error);
-    }
-
-    priv->pending_results = g_queue_new ();
-
-    for (l = priv->results; l != NULL; l = g_list_next (l))
-    {
-        g_queue_push_tail (priv->pending_results, l->data);
     }
 
-    priv->insert_idle_id = g_idle_add ((GSourceFunc) insert_idle,
-                                       view);
-    g_source_set_name_by_id (priv->insert_idle_id, G_STRFUNC);
+    return G_SOURCE_CONTINUE;
 }
 
 static gchar *
@@ -510,7 +459,7 @@ on_notify_category (GlCategoryList *list,
             g_assert_not_reached ();
     }
 
-    gl_journal_query_async (priv->journal, NULL, query_ready, view);
+    priv->insert_idle_id = g_idle_add (insert_idle, view);
 
     gtk_widget_show_all (GTK_WIDGET (priv->active_listbox));
 
@@ -657,7 +606,6 @@ gl_event_view_list_finalize (GObject *object)
     }
 
     g_clear_pointer (&priv->search_text, g_free);
-    g_clear_pointer (&priv->pending_results, g_queue_free);
 }
 
 static void
diff --git a/src/gl-journal.c b/src/gl-journal.c
index 1bb09ea..17e986c 100644
--- a/src/gl-journal.c
+++ b/src/gl-journal.c
@@ -312,33 +312,6 @@ out:
     return NULL;
 }
 
-void
-gl_journal_query_async (GlJournal *self,
-                        GCancellable *cancellable,
-                        GAsyncReadyCallback callback,
-                        gpointer user_data)
-{
-    GTask *task;
-    GList *results;
-
-    task = g_task_new (self, cancellable, callback, user_data);
-
-    results = gl_journal_query (self);
-    g_task_return_pointer (task, results, (GDestroyNotify) gl_journal_results_free);
-
-    g_object_unref (task);
-}
-
-GList *
-gl_journal_query_finish (GlJournal *self,
-                         GAsyncResult *res,
-                         GError **error)
-{
-    g_return_val_if_fail (g_task_is_valid (res, self), NULL);
-
-    return g_task_propagate_pointer (G_TASK (res), error);
-}
-
 /**
  * gl_journal_query_match:
  * @query: a @query to match against the current log entry
@@ -378,83 +351,22 @@ gl_journal_query_match (sd_journal          *journal,
   return TRUE;
 }
 
-GList *
-gl_journal_query (GlJournal *self)
+static gchar *
+create_boot_id_match_string (void)
 {
-    GlJournalPrivate *priv;
-    sd_journal *journal;
-    gint ret;
-    GList *results = NULL;
-
-    g_return_val_if_fail (GL_JOURNAL (self), NULL);
-
-    priv = gl_journal_get_instance_private (self);
-    journal = priv->journal;
-
-    /* Take events from this boot only. */
     sd_id128_t boot_id;
     gchar boot_string[33];
-    gchar *match_string;
+    int r;
 
-    ret = sd_id128_get_boot (&boot_id);
-
-    if (ret < 0)
+    r = sd_id128_get_boot (&boot_id);
+    if (r < 0)
     {
-        g_warning ("Error getting boot ID of running kernel: %s",
-                   g_strerror (-ret));
+        g_warning ("Error getting boot ID of running kernel: %s", g_strerror (-r));
+        return NULL;
     }
 
     sd_id128_to_string (boot_id, boot_string);
-
-    match_string = g_strconcat ("_BOOT_ID=", boot_string, NULL);
-
-    ret = sd_journal_add_match (journal, match_string, 0);
-
-    if (ret < 0)
-    {
-        g_warning ("Error adding match '%s': %s", match_string,
-                   g_strerror (-ret));
-    }
-
-    g_free (match_string);
-
-    ret = sd_journal_seek_head (journal);
-
-    if (ret < 0)
-    {
-        g_warning ("Error seeking to start of systemd journal: %s",
-                   g_strerror (-ret));
-    }
-
-    do
-    {
-        GlJournalResult *result;
-
-        ret = sd_journal_next (journal);
-
-        if (ret < 0)
-        {
-            g_warning ("Error setting cursor to next position in systemd journal: %s",
-                       g_strerror (-ret));
-            break;
-        }
-        else if (ret == 0)
-        {
-            g_debug ("End of systemd journal reached");
-            break;
-        }
-
-        if (!gl_journal_query_match (journal, (const gchar * const *) priv->mandatory_fields))
-            continue;
-
-        result = _gl_journal_query_result (self);
-
-        results = g_list_prepend (results, result);
-    } while (TRUE);
-
-    sd_journal_flush_matches (journal);
-
-    return results;
+    return g_strconcat ("_BOOT_ID=", boot_string, NULL);
 }
 
 /**
@@ -471,7 +383,9 @@ gl_journal_set_matches (GlJournal           *journal,
 {
     GlJournalPrivate *priv = gl_journal_get_instance_private (journal);
     GPtrArray *mandatory_fields;
+    int r;
     gint i;
+    gboolean has_boot_id;
 
     g_return_if_fail (matches != NULL);
 
@@ -483,8 +397,6 @@ gl_journal_set_matches (GlJournal           *journal,
     mandatory_fields = g_ptr_array_new ();
     for (i = 0; matches[i]; i++)
     {
-        int r;
-
         /* matches without a value should only check for existence.
          * systemd doesn't support that, so let's remember them to
          * filter out later.
@@ -495,6 +407,9 @@ gl_journal_set_matches (GlJournal           *journal,
             continue;
         }
 
+        if (g_str_has_prefix (matches[i], "_BOOT_ID="))
+          has_boot_id = TRUE;
+
         r = sd_journal_add_match (priv->journal, matches[i], 0);
         if (r < 0)
         {
@@ -506,7 +421,50 @@ gl_journal_set_matches (GlJournal           *journal,
     /* add sentinel */
     g_ptr_array_add (mandatory_fields, NULL);
 
+    /* take events from this boot only, unless _BOOT_ID was in @matches */
+    if (!has_boot_id)
+    {
+        gchar *match;
+
+        match = create_boot_id_match_string ();
+        if (match)
+        {
+            r = sd_journal_add_match (priv->journal, match, 0);
+            if (r < 0)
+                g_warning ("Failed to add match '%s': %s", matches[i], g_strerror (-r));
+
+            g_free (match);
+        }
+    }
+
     priv->mandatory_fields = (gchar **) g_ptr_array_free (mandatory_fields, FALSE);
+
+    r = sd_journal_seek_tail (priv->journal);
+    if (r < 0)
+        g_warning ("Error seeking to start of systemd journal: %s", g_strerror (-r));
+}
+
+GlJournalResult *
+gl_journal_previous (GlJournal *journal)
+{
+    GlJournalPrivate *priv = gl_journal_get_instance_private (journal);
+    gint r;
+
+    r = sd_journal_previous (priv->journal);
+    if (r < 0)
+    {
+        g_warning ("Failed to fetch previous log entry: %s", g_strerror (-r));
+        return NULL;
+    }
+
+    if (r == 0) /* end */
+        return NULL;
+
+    /* filter this one out because of a non-existent field */
+    if (!gl_journal_query_match (priv->journal, (const gchar * const *) priv->mandatory_fields))
+        return gl_journal_previous (journal);
+
+    return _gl_journal_query_result (journal);
 }
 
 static void
diff --git a/src/gl-journal.h b/src/gl-journal.h
index 3b46532..4b0cb64 100644
--- a/src/gl-journal.h
+++ b/src/gl-journal.h
@@ -76,10 +76,8 @@ typedef struct
 
 GType gl_journal_result_get_type (void);
 GType gl_journal_get_type (void);
-void gl_journal_query_async (GlJournal *self, GCancellable *cancellable, GAsyncReadyCallback callback, 
gpointer user_data);
-GList * gl_journal_query_finish (GlJournal *self, GAsyncResult *res, GError **error);
-GList * gl_journal_query (GlJournal *self);
 void gl_journal_set_matches (GlJournal *journal, const gchar * const *matches);
+GlJournalResult * gl_journal_previous (GlJournal *journal);
 GlJournalResult * gl_journal_result_ref (GlJournalResult *result);
 void gl_journal_result_unref (GlJournalResult *result);
 void gl_journal_results_free (GList *results);


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