summaryrefslogtreecommitdiff
path: root/src/gl-journal.c
diff options
context:
space:
mode:
authorJonathan Kang <jonathan121537@gmail.com>2015-06-19 17:16:02 +0800
committerDavid King <davidk@gnome.org>2015-07-01 16:10:17 +0100
commit45c6a49a84d730165d107f3677215912ffe18e79 (patch)
tree75cc989af6d27bb00d776abbf5a8b25a45e80f8b /src/gl-journal.c
parent67561cd0f4cc0140ea9b4be9c7bb533d0396fe6a (diff)
downloadgnome-logs-45c6a49a84d730165d107f3677215912ffe18e79.tar.gz
View events from different boots
https://bugzilla.gnome.org/show_bug.cgi?id=726229
Diffstat (limited to 'src/gl-journal.c')
-rw-r--r--src/gl-journal.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/gl-journal.c b/src/gl-journal.c
index 6147572..942dde6 100644
--- a/src/gl-journal.c
+++ b/src/gl-journal.c
@@ -42,12 +42,19 @@ struct _GlJournalEntry
G_DEFINE_TYPE (GlJournalEntry, gl_journal_entry, G_TYPE_OBJECT);
+/* "_BOOT_ID=" contains 9 characters, and 33 more characters is needed to
+ * store the string formated from a 128-bit ID. The ID will be formatted as
+ * 32 lowercase hexadecimal digits and be terminated by a NUL byte. So an
+ * array of with a size 42 is need. */
+static char match[42] = "_BOOT_ID=";
+
typedef struct
{
sd_journal *journal;
gint fd;
guint source_id;
gchar **mandatory_fields;
+ GArray *boot_ids;
} GlJournalPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GlJournal, gl_journal, G_TYPE_OBJECT)
@@ -58,6 +65,105 @@ gl_journal_error_quark (void)
return g_quark_from_static_string ("gl-journal-error-quark");
}
+static gint
+boot_id_cmp (const void *a, const void *b)
+{
+ guint64 _a, _b;
+
+ _a = ((const GlJournalBootID *)a)->realtime;
+ _b = ((const GlJournalBootID *)b)->realtime;
+
+ return _a < _b ? -1 : (_a > _b ? 1 : 0);
+}
+
+static void
+gl_journal_get_boots (GlJournal *journal)
+{
+ GlJournalPrivate *priv;
+ int r;
+ const void *data;
+ size_t length;
+
+ g_return_if_fail (GL_JOURNAL (journal));
+
+ priv = gl_journal_get_instance_private (journal);
+
+ r = sd_journal_query_unique (priv->journal, "_BOOT_ID");
+ if (r < 0)
+ {
+ g_warning ("Error reading unique data fields: %s", g_strerror (-r));
+ }
+
+ SD_JOURNAL_FOREACH_UNIQUE (priv->journal, data, length)
+ {
+ gchar *boot_match;
+ GlJournalBootID boot_id;
+ sd_id128_t id;
+
+ r = sd_id128_from_string (((const char *)data) + strlen ("_BOOT_ID="),
+ &id);
+ if (r < 0)
+ {
+ g_warning ("Error parsing strings into 128-bit IDs: %s",
+ g_strerror (-r));
+ continue;
+ }
+
+ /* convert id.boot_id into boot_match */
+ sd_id128_to_string (id, match + 9);
+ boot_match = g_strdup (match);
+ boot_id.boot_match = boot_match;
+
+ r = sd_journal_add_match (priv->journal, data, length);
+ if (r < 0)
+ {
+ g_warning ("Error adding entry match: %s", g_strerror (-r));
+ }
+
+ r = sd_journal_seek_head (priv->journal);
+ if (r < 0)
+ {
+ g_warning ("Error seeking to the beginning of the journal: %s\n",
+ g_strerror (-r));
+ }
+
+ r = sd_journal_next (priv->journal);
+ if (r < 0)
+ {
+ g_warning ("Error advance the read pointer in the journal: %s",
+ g_strerror (-r));
+ }
+ else if (r == 0)
+ {
+ goto flush;
+ }
+
+ r = sd_journal_get_realtime_usec (priv->journal, &boot_id.realtime);
+ if (r < 0)
+ {
+ g_warning ("Error retrieving the sender timestamps: %s",
+ g_strerror (-r));
+ }
+
+ priv->boot_ids = g_array_append_val (priv->boot_ids, boot_id);
+
+ flush:
+ sd_journal_flush_matches (priv->journal);
+ }
+
+ g_array_sort (priv->boot_ids, boot_id_cmp);
+}
+
+GArray *
+gl_journal_get_boot_ids (GlJournal *journal)
+{
+ GlJournalPrivate *priv;
+
+ priv = gl_journal_get_instance_private (journal);
+
+ return priv->boot_ids;
+}
+
static gboolean
on_journal_changed (gint fd,
GIOCondition condition,
@@ -91,12 +197,23 @@ on_journal_changed (gint fd,
static void
gl_journal_finalize (GObject *object)
{
+ guint i;
GlJournal *journal = GL_JOURNAL (object);
GlJournalPrivate *priv = gl_journal_get_instance_private (journal);
g_source_remove (priv->source_id);
g_clear_pointer (&priv->journal, sd_journal_close);
g_clear_pointer (&priv->mandatory_fields, g_strfreev);
+
+ for (i = 0; i < priv->boot_ids->len; i++)
+ {
+ GlJournalBootID *boot_id;
+
+ boot_id = &g_array_index (priv->boot_ids, GlJournalBootID, i);
+
+ g_free (boot_id->boot_match);
+ }
+ g_array_free (priv->boot_ids, TRUE);
}
static void
@@ -160,6 +277,9 @@ gl_journal_init (GlJournal *self)
g_debug ("Immediate wakeups expected for systemd journal activity");
}
+ priv->boot_ids = g_array_new (FALSE, TRUE, sizeof (GlJournalBootID));
+
+ gl_journal_get_boots (self);
}
static gchar *