[tracker-miners/sam/index-file-sync: 17/18] cli: Add status feedback and monitor mode to `tracker index`



commit 9e3b78cbd4af2c8772584dc40663e72ba3a749a0
Author: Sam Thursfield <sam afuera me uk>
Date:   Sun Mar 8 19:12:31 2020 +0100

    cli: Add status feedback and monitor mode to `tracker index`
    
    This commit adds a --monitor mode to `tracker index`, which
    wraps the IndexFileForProcess functionality. It lets users
    trigger crawling and monitoring of locations which aren't
    configured for automatic indexing.
    
    The default `tracker index` behavior will in future be to
    wait until the miner and extractor have processed the locations
    specified, and report the results to the user.
    
    https://gitlab.gnome.org/GNOME/tracker/issues/122

 docs/manpages/tracker-index.1                      |  21 ++--
 .../tracker-miners-common.h                        |   2 +-
 src/tracker/tracker-index.c                        | 122 ++++++++++++++++++++-
 src/tracker/tracker-miner-manager.c                |  82 ++++++++++----
 src/tracker/tracker-miner-manager.h                |  26 ++---
 5 files changed, 206 insertions(+), 47 deletions(-)
---
diff --git a/docs/manpages/tracker-index.1 b/docs/manpages/tracker-index.1
index b8201b7fa..56e132ddd 100644
--- a/docs/manpages/tracker-index.1
+++ b/docs/manpages/tracker-index.1
@@ -5,19 +5,26 @@ tracker-index \- Index content using the Tracker filesystem miner
 
 .SH SYNOPSIS
 .nf
-\fBtracker index\fR <\fIpath\fR> [[\fIpath\fR] ...]
+\fBtracker index\fR <\fIPATH\fR> [[\fIPATH\fR] ...]
+\fBtracker index\fR [\-\-monitor] <\fIDIR\fR> [[\fIDIR\fR] ...]
 .fi
 
 .SH DESCRIPTION
 This command causes the Tracker filesystem miner to process the given
 files or directories.
 
-Usually you should configure the miner to automatically index your
-content, because it will monitor the content locations for changes
-and ensure that the index is kept up to date. Content that is added
-using `tracker index` will not be monitored for changes by default,
-so you can end up with stale data in your search results if you use
-this command.
+Content added using \fBtracker index\fR will not be monitored for changes by
+default, so you can end up with stale data in your search results.
+
+Use \fB\-\-monitor\fR mode to avoid stale data. In this mode, the command will
+not exit until CTRL+C is pressed, and on exit the content will be removed from
+the store again.
+
+It's often more convenient to configure the filesystem miner to index your
+content automatically, rather than using this command.
+.TP
+.B \-m, \-\-monitor
+Trigger indexing and wait for CTRL+C, removing the data again on exit.
 
 .SH SEE ALSO
 .BR tracker (1).
diff --git a/src/libtracker-miners-common/tracker-miners-common.h 
b/src/libtracker-miners-common/tracker-miners-common.h
index 01a2ad115..1c605d41e 100644
--- a/src/libtracker-miners-common/tracker-miners-common.h
+++ b/src/libtracker-miners-common/tracker-miners-common.h
@@ -21,7 +21,7 @@
 #define __LIBTRACKER_MINERS_COMMON_H__
 
 #if !defined (__LIBTRACKER_MINERS_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION)
-#error "only <libtracker-miners-common/tracker-common.h> must be included directly."
+#error "only <libtracker-miners-common/tracker-miners-common.h> must be included directly."
 #endif
 
 #include <glib.h>
diff --git a/src/tracker/tracker-index.c b/src/tracker/tracker-index.c
index fc28deefd..38cf8c7c6 100644
--- a/src/tracker/tracker-index.c
+++ b/src/tracker/tracker-index.c
@@ -27,6 +27,7 @@
 #endif
 
 #include <glib.h>
+#include <glib-unix.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include <locale.h>
@@ -36,9 +37,13 @@
 #include "tracker-dbus.h"
 #include "tracker-miner-manager.h"
 
+static gboolean monitor_mode;
 static gchar **filenames;
 
 static GOptionEntry entries[] = {
+       { "monitor", 'm', 0, G_OPTION_ARG_NONE, &monitor_mode,
+         N_("Trigger indexing and wait for CTRL+C, removing the data again on exit."),
+         NULL },
        { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames,
          N_("FILE"),
          N_("FILE") },
@@ -85,10 +90,125 @@ index_or_reindex_file (void)
        return EXIT_SUCCESS;
 }
 
+static void
+miner_file_processed (TrackerMinerManager *miner_manager,
+                      const gchar         *miner,
+                      const gchar         *uri,
+                      const gboolean       status,
+                      const gchar         *message,
+                      GFile               *root)
+{
+       g_autoptr(GFile) file = NULL;
+       g_autoptr(GError) error = NULL;
+       g_autofree gchar *relative_path = NULL;
+
+       file = g_file_new_for_uri (uri);
+
+       relative_path = g_file_get_relative_path (root, file);
+
+       if (g_file_equal (root, file) || relative_path != NULL) {
+               /* File is a child of the root. */
+               g_debug ("File processed: %s: %s, %i, %s\n", miner, uri, status, message);
+       }
+}
+
+static gboolean
+sigterm_cb (gpointer user_data)
+{
+       g_message ("Received signal");
+
+       g_main_loop_quit (user_data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static gint
+index_or_reindex_file_monitor_mode (void)
+{
+       g_autoptr(TrackerMinerManager) manager = NULL;
+       g_autoptr(GMainLoop) main_loop = NULL;
+       g_autoptr(GError) error = NULL;
+       gchar **p;
+
+       /* Check we were only passed directories. IndexFileForProcess doesn't work
+        * for files. */
+       for (p = filenames; *p; p++) {
+               g_autoptr(GFile) path = NULL;
+               g_autoptr(GFileInfo) info = NULL;
+
+               path = g_file_new_for_commandline_arg (*p);
+               info = g_file_query_info (path,
+                                         G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                         G_FILE_QUERY_INFO_NONE,
+                                         NULL,
+                                         &error);
+
+               if (error) {
+                       g_printerr ("%s: %s\n",
+                                   _("Error determining file type"),
+                                   error->message);
+                       return EXIT_FAILURE;
+               }
+
+               if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) {
+                       g_printerr (_("Could not index file %s: in `--monitor` mode, "
+                                     "only directories can be indexed.\n"),
+                                   g_file_peek_path (path));
+                       return EXIT_FAILURE;
+               }
+       }
+
+       /* Auto-start the miners here if we need to */
+       manager = tracker_miner_manager_new_full (TRUE, &error);
+       if (!manager) {
+               g_printerr (_("Could not (re)index file, manager could not be created, %s"),
+                           error ? error->message : _("No error given"));
+               g_printerr ("\n");
+               return EXIT_FAILURE;
+       }
+
+       for (p = filenames; *p; p++) {
+               g_autoptr(GFile) dir = NULL;
+
+               dir = g_file_new_for_commandline_arg (*p);
+
+               g_signal_connect_data (G_OBJECT (manager),
+                                      "miner-file-processed",
+                                      G_CALLBACK (miner_file_processed),
+                                      g_object_ref (dir),
+                                      (GClosureNotify)g_object_unref,
+                                      0);
+
+               tracker_miner_manager_index_file_for_process (manager, dir, NULL, &error);
+
+               if (error) {
+                       g_printerr ("%s: %s\n",
+                                   _("Could not (re)index directory"),
+                                   error->message);
+                       return EXIT_FAILURE;
+               }
+
+               g_print ("%s\n", _("(Re)indexing directory was successful"));
+       }
+
+       main_loop = g_main_loop_new (NULL, 0);
+
+       g_unix_signal_add (SIGINT, sigterm_cb, main_loop);
+       g_unix_signal_add (SIGTERM, sigterm_cb, main_loop);
+
+       g_main_loop_run (main_loop);
+
+       return EXIT_SUCCESS;
+}
+
 static int
 index_run (void)
 {
-       return index_or_reindex_file ();
+       if (monitor_mode) {
+               return index_or_reindex_file_monitor_mode ();
+       } else {
+               return index_or_reindex_file ();
+       }
 }
 
 int
diff --git a/src/tracker/tracker-miner-manager.c b/src/tracker/tracker-miner-manager.c
index 8e5b2d2c3..8a1123396 100644
--- a/src/tracker/tracker-miner-manager.c
+++ b/src/tracker/tracker-miner-manager.c
@@ -66,6 +66,7 @@ struct MinerData {
        guint progress_signal;
        guint paused_signal;
        guint resumed_signal;
+       guint file_processed_signal;
        guint watch_name_id;
        GObject *manager; /* weak */
 };
@@ -98,6 +99,8 @@ G_DEFINE_TYPE_WITH_CODE (TrackerMinerManager, tracker_miner_manager, G_TYPE_OBJE
                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                 miner_manager_initable_iface_init));
 
+G_DEFINE_QUARK (tracker-miner-manager-error, tracker_miner_manager_error)
+
 enum {
        PROP_0,
        PROP_AUTO_START,
@@ -110,6 +113,7 @@ enum {
        MINER_RESUMED,
        MINER_ACTIVATED,
        MINER_DEACTIVATED,
+       MINER_FILE_PROCESSED,
        LAST_SIGNAL
 };
 
@@ -242,6 +246,32 @@ tracker_miner_manager_class_init (TrackerMinerManagerClass *klass)
                              NULL,
                              G_TYPE_NONE, 1,
                              G_TYPE_STRING);
+
+       /**
+        * TrackerMinerManager::miner-file-processed:
+        * @manager: the #TrackerMinerManager
+        * @miner: miner reference
+        * @file: URI of the file processed
+        * @status: Successfully indexed the resource.
+        * @message: Error or warning message, if any.
+        *
+        * The ::miner-file-processed signal will be emitted whenever a
+        * miner successfully processes a resource.
+        *
+        * Since: 3.0
+        **/
+       signals [MINER_FILE_PROCESSED] =
+               g_signal_new ("miner-file-processed",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (TrackerMinerManagerClass, miner_file_processed),
+                             NULL, NULL,
+                             NULL,
+                             G_TYPE_NONE, 4,
+                             G_TYPE_STRING,
+                             G_TYPE_STRING,
+                             G_TYPE_BOOLEAN,
+                             G_TYPE_STRING);
 }
 
 static void
@@ -389,11 +419,32 @@ miner_resumed (GDBusConnection *connection,
                gpointer         user_data)
 {
        MinerData *data = user_data;
+
        if (data->manager) {
                g_signal_emit (data->manager, signals[MINER_RESUMED], 0, data->dbus_name);
        }
 }
 
+static void
+miner_file_processed (GDBusConnection *connection,
+                      const gchar     *sender_name,
+                      const gchar     *object_path,
+                      const gchar     *interface_name,
+                      const gchar     *signal_name,
+                      GVariant        *parameters,
+                      gpointer         user_data)
+{
+       MinerData *data = user_data;
+       const gchar *url = NULL;
+       gboolean status = FALSE;
+       const gchar *message = NULL;
+
+       g_variant_get (parameters, "(&sbs)", &url, &status, &message);
+       if (data->manager) {
+               g_signal_emit (data->manager, signals[MINER_FILE_PROCESSED], 0, data->dbus_name, url, status, 
message);
+       }
+}
+
 static void
 data_manager_weak_notify (gpointer user_data, GObject *old_object)
 {
@@ -502,6 +553,17 @@ miner_manager_initable_init (GInitable     *initable,
                                                                           data,
                                                                           NULL);
 
+               data->file_processed_signal = g_dbus_connection_signal_subscribe (priv->connection,
+                                                                                 data->dbus_name,
+                                                                                 
TRACKER_MINER_DBUS_INTERFACE,
+                                                                                 "FileProcessed",
+                                                                                 data->dbus_path,
+                                                                                 NULL,
+                                                                                 G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                                 miner_file_processed,
+                                                                                 data,
+                                                                                 NULL);
+
                g_hash_table_insert (priv->miner_proxies, proxy, g_strdup (data->dbus_name));
 
                data->watch_name_id = g_bus_watch_name (TRACKER_IPC_BUS,
@@ -1386,26 +1448,6 @@ tracker_miner_manager_get_description (TrackerMinerManager *manager,
        return NULL;
 }
 
-/**
- * tracker_miner_manager_error_quark:
- *
- * Returns: the #GQuark used to identify miner manager errors in
- * GError structures.
- *
- * Since: 0.8
- **/
-GQuark
-tracker_miner_manager_error_quark (void)
-{
-       static GQuark error_quark = 0;
-
-       if (G_UNLIKELY (error_quark == 0)) {
-               error_quark = g_quark_from_static_string ("tracker-miner-manager-error-quark");
-       }
-
-       return error_quark;
-}
-
 
 static gboolean
 miner_manager_index_file_sync (TrackerMinerManager *manager,
diff --git a/src/tracker/tracker-miner-manager.h b/src/tracker/tracker-miner-manager.h
index de77b48e0..0b75c47b4 100644
--- a/src/tracker/tracker-miner-manager.h
+++ b/src/tracker/tracker-miner-manager.h
@@ -29,16 +29,10 @@
 G_BEGIN_DECLS
 
 #define TRACKER_TYPE_MINER_MANAGER         (tracker_miner_manager_get_type())
-#define TRACKER_MINER_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_MANAGER, 
TrackerMinerManager))
-#define TRACKER_MINER_MANAGER_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    TRACKER_TYPE_MINER_MANAGER, 
TrackerMinerManagerClass))
-#define TRACKER_IS_MINER_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_MANAGER))
-#define TRACKER_IS_MINER_MANAGER_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c),    TRACKER_TYPE_MINER_MANAGER))
-#define TRACKER_MINER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),  TRACKER_TYPE_MINER_MANAGER, 
TrackerMinerManagerClass))
+G_DECLARE_DERIVABLE_TYPE (TrackerMinerManager, tracker_miner_manager, TRACKER, MINER_MANAGER, GObject)
 
 #define TRACKER_MINER_MANAGER_ERROR tracker_miner_manager_error_quark ()
 
-typedef struct _TrackerMinerManager TrackerMinerManager;
-
 /**
  * TrackerMinerManagerError:
  * @TRACKER_MINER_MANAGER_ERROR_NOT_AVAILABLE: The miner in question
@@ -56,15 +50,6 @@ typedef enum {
        TRACKER_MINER_MANAGER_ERROR_NOENT
 } TrackerMinerManagerError;
 
-/**
- * TrackerMinerManager:
- *
- * Object to query and control miners.
- **/
-struct _TrackerMinerManager {
-       GObject parent_instance;
-};
-
 /**
  * TrackerMinerManagerClass:
  * @miner_progress: The progress signal for all miners including name,
@@ -75,8 +60,9 @@ struct _TrackerMinerManager {
  * indicates the miner is available on d-bus.
  * @miner_deactivated: The deactivate for all miners which indicates
  * the miner is no longer available on d-bus.
+ * @miner_file_processed: Status update for a single file or unit.
  **/
-typedef struct {
+struct _TrackerMinerManagerClass {
        GObjectClass parent_class;
 
        void (* miner_progress)    (TrackerMinerManager *manager,
@@ -91,7 +77,11 @@ typedef struct {
                                    const gchar         *miner_name);
        void (* miner_deactivated) (TrackerMinerManager *manager,
                                    const gchar         *miner_name);
-} TrackerMinerManagerClass;
+       void (* miner_file_processed) (TrackerMinerManager *manager,
+                                      const gchar         *uri,
+                                      const gboolean      *status,
+                                      const gchar         *message);
+};
 
 GType                tracker_miner_manager_get_type           (void) G_GNUC_CONST;
 GQuark               tracker_miner_manager_error_quark        (void) G_GNUC_CONST;


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