From c9f2292339540d4b9d8940bcef16b7485480c8d9 Mon Sep 17 00:00:00 2001
From: William Jon McCann <jmccann@redhat.com>
Date: Fri, 11 Jun 2010 19:53:22 +0000
Subject: Add a --since option to show entries in a time window

Doesn't load any history files it doesn't need to which should
help performance on systems with long histories.

https://bugs.freedesktop.org/show_bug.cgi?id=25660
---
diff --git a/tools/ck-history.c b/tools/ck-history.c
index 606106c..d02caaa 100644
--- a/tools/ck-history.c
+++ b/tools/ck-history.c
@@ -62,8 +62,8 @@ typedef enum {
 
 static GList *all_events = NULL;
 
-static gboolean
-process_event_line (const char *line)
+static CkLogEvent *
+parse_event_line (const char *line)
 {
         GString    *str;
         CkLogEvent *event;
@@ -72,47 +72,80 @@ process_event_line (const char *line)
         event = ck_log_event_new_from_string (str);
         g_string_free (str, TRUE);
 
-        if (event != NULL) {
-                all_events = g_list_prepend (all_events, event);
-        }
-
-        return TRUE;
+        return event;
 }
 
 static gboolean
-process_log_gzstream (gzFile *fstream)
+process_log_gzstream (gzFile   *fstream,
+                      GTimeVal *since)
 {
-        char line[MAX_LINE_LEN];
+        char     line[MAX_LINE_LEN];
+        gboolean hit_since;
+        GList   *events;
 
+        events = NULL;
+        hit_since = FALSE;
         while (gzgets (fstream, line, sizeof (line)) != Z_NULL) {
+                CkLogEvent *event;
+
                 if (strlen (line) == sizeof (line) - 1) {
                         g_warning ("Log line truncated");
                 }
 
-                process_event_line (line);
+                event = parse_event_line (line);
+                if (event == NULL) {
+                        continue;
+                }
+
+                if (since == NULL || event->timestamp.tv_sec >= since->tv_sec) {
+                        events = g_list_prepend (events, event);
+                } else {
+                        hit_since = TRUE;
+                }
         }
 
-        return TRUE;
+        all_events = g_list_concat (all_events, events);
+
+        return !hit_since;
 }
 
 static gboolean
-process_log_stream (FILE *fstream)
+process_log_stream (FILE     *fstream,
+                    GTimeVal *since)
 {
-        char line[MAX_LINE_LEN];
+        char     line[MAX_LINE_LEN];
+        gboolean hit_since;
+        GList   *events;
 
+        events = NULL;
+        hit_since = FALSE;
         while (fgets (line, sizeof (line), fstream) != NULL) {
+                CkLogEvent *event;
+
                 if (strlen (line) == sizeof (line) - 1) {
                         g_warning ("Log line truncated");
                 }
 
-                process_event_line (line);
+                event = parse_event_line (line);
+                if (event == NULL) {
+                        continue;
+                }
+
+                if (since == NULL || event->timestamp.tv_sec >= since->tv_sec) {
+                        events = g_list_prepend (events, event);
+                } else {
+                        hit_since = TRUE;
+                }
         }
 
-        return TRUE;
+        all_events = g_list_concat (all_events, events);
+
+        return !hit_since;
 }
 
 static gboolean
-process_log_file (const char *filename)
+process_log_file (const char *filename,
+                  GTimeVal   *since)
 {
         gboolean ret;
 
@@ -131,7 +164,7 @@ process_log_file (const char *filename)
                                    errmsg);
                         return FALSE;
                 }
-                ret = process_log_gzstream (f);
+                ret = process_log_gzstream (f, since);
                 gzclose (f);
         } else {
                 FILE    *f;
@@ -143,7 +176,7 @@ process_log_file (const char *filename)
                                    g_strerror (errno));
                         return FALSE;
                 }
-                ret = process_log_stream (f);
+                ret = process_log_stream (f, since);
                 fclose (f);
         }
 
@@ -180,11 +213,14 @@ get_log_file_list (void)
                 files = g_list_prepend (files, filename);
         };
 
+        /* Return the list in reverse time order, newest first */
+        files = g_list_reverse (files);
+
         return files;
 }
 
 static gboolean
-process_logs (void)
+process_logs (GTimeVal *since)
 {
         gboolean ret;
         GList   *files;
@@ -199,8 +235,7 @@ process_logs (void)
                 char    *filename;
 
                 filename = l->data;
-
-                res = process_log_file (filename);
+                res = process_log_file (filename, since);
                 if (! res) {
                         goto out;
                 }
@@ -843,6 +878,8 @@ main (int    argc,
         GError             *error = NULL;
         int                 report_type;
         int                 uid;
+        GTimeVal            timestamp;
+        gboolean            use_since;
         static gboolean     do_version = FALSE;
         static gboolean     report_last_compat = FALSE;
         static gboolean     report_last = FALSE;
@@ -851,6 +888,7 @@ main (int    argc,
         static char        *username = NULL;
         static char        *seat = NULL;
         static char        *session_type = NULL;
+        static char        *since = NULL;
         static GOptionEntry entries [] = {
                 { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
                 { "frequent", 0, 0, G_OPTION_ARG_NONE, &report_frequent, N_("Show listing of frequent users"), NULL },
@@ -860,6 +898,7 @@ main (int    argc,
                 { "seat", 's', 0, G_OPTION_ARG_STRING, &seat, N_("Show entries for the specified seat"), N_("SEAT") },
                 { "session-type", 't', 0, G_OPTION_ARG_STRING, &session_type, N_("Show entries for the specified session type"), N_("TYPE") },
                 { "user", 'u', 0, G_OPTION_ARG_STRING, &username, N_("Show entries for the specified user"), N_("NAME") },
+                { "since", 0, 0, G_OPTION_ARG_STRING, &since, N_("Show entries since the specified time (ISO 8601 format)"), N_("DATETIME") },
                 { NULL }
         };
 
@@ -880,6 +919,15 @@ main (int    argc,
                 exit (1);
         }
 
+        use_since = FALSE;
+        if (since != NULL) {
+                use_since = g_time_val_from_iso8601 (since, &timestamp);
+                if (! use_since) {
+                        g_warning ("Invalid ISO 8601 time value");
+                        exit (1);
+                }
+        }
+
         if (report_last_compat) {
                 report_type = REPORT_TYPE_LAST_COMPAT;
         } else if (report_last) {
@@ -902,7 +950,11 @@ main (int    argc,
                 uid = -1;
         }
 
-        process_logs ();
+        if (use_since) {
+                process_logs (&timestamp);
+        } else {
+                process_logs (NULL);
+        }
         generate_report (report_type, uid, seat, session_type);
         free_events ();
 
--
cgit v0.8.3-6-g21f6