From f9c79fce6d90e7e5842f2c56a1ec98a151126874 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Sat, 1 Aug 2020 17:25:27 +0200 Subject: Use Tracker Miners inside Flatpak when not available on the host This means the Nautilus flatpak will be able to use Tracker on systems which don't have Tracker 3 available on the host. It comes at a cost of increased resource consumption inside the Flatpak due running an extra indexer process there. --- data/meson.build | 1 + data/tracker/meson.build | 31 ++++++ ...nome.Nautilus.Tracker3.Miner.Extract.service.in | 7 ++ ....gnome.Nautilus.Tracker3.Miner.Files.service.in | 7 ++ data/tracker/org.gnome.Nautilus.domain.rule.in | 21 ++++ meson.build | 2 +- src/nautilus-batch-rename-utilities.c | 5 +- src/nautilus-search-engine-tracker.c | 9 +- src/nautilus-tag-manager.c | 68 ++++++------ src/nautilus-tracker-utilities.c | 120 +++++++++++++++++++++ src/nautilus-tracker-utilities.h | 6 +- 11 files changed, 236 insertions(+), 41 deletions(-) create mode 100644 data/tracker/meson.build create mode 100644 data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in create mode 100644 data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in create mode 100644 data/tracker/org.gnome.Nautilus.domain.rule.in diff --git a/data/meson.build b/data/meson.build index e51ed50b1..9a4e2ff52 100644 --- a/data/meson.build +++ b/data/meson.build @@ -139,3 +139,4 @@ if appstream_util.found() endif subdir('ontology') +subdir('tracker') diff --git a/data/tracker/meson.build b/data/tracker/meson.build new file mode 100644 index 000000000..5320af164 --- /dev/null +++ b/data/tracker/meson.build @@ -0,0 +1,31 @@ +# Files needed for running Tracker inside the Flatpak sandbox, for systems +# which don't have a suitable version of Tracker in the host OS. +# +# We must export the .service files from the sandbox so they work on the +# session bus. This means the Tracker domain name must correspond with the +# application ID. + +domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies' +dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services' + +tracker_domain_config = configuration_data() +tracker_domain_config.set('application_id', application_id) +tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / application_id + '.domain.rule') + +configure_file( + input: 'org.gnome.Nautilus.domain.rule.in', + output: application_id + '.domain.rule', + configuration: tracker_domain_config, + install_dir: domain_ontologies_dir) + +configure_file( + input: 'org.gnome.Nautilus.Tracker3.Miner.Extract.service.in', + output: application_id + '.Tracker3.Miner.Extract.service', + configuration: tracker_domain_config, + install_dir: dbus_services_dir) + +configure_file( + input: 'org.gnome.Nautilus.Tracker3.Miner.Files.service.in', + output: application_id + '.Tracker3.Miner.Files.service', + configuration: tracker_domain_config, + install_dir: dbus_services_dir) diff --git a/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in new file mode 100644 index 000000000..eb7a87aa6 --- /dev/null +++ b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in @@ -0,0 +1,7 @@ +[D-BUS Service] +Name=@application_id@.Tracker3.Miner.Extract +Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@ + +# Miner details needed for tracker-control +Path=/org/freedesktop/Tracker3/Miner/Extract +NameSuffix=Miner.Files diff --git a/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in new file mode 100644 index 000000000..4fa7371d1 --- /dev/null +++ b/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in @@ -0,0 +1,7 @@ +[D-BUS Service] +Name=@application_id@.Tracker3.Miner.Files +Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0 + +# Miner details needed for tracker-control +Path=/org/freedesktop/Tracker3/Miner/Files +NameSuffix=Miner.Files diff --git a/data/tracker/org.gnome.Nautilus.domain.rule.in b/data/tracker/org.gnome.Nautilus.domain.rule.in new file mode 100644 index 000000000..ec0808e30 --- /dev/null +++ b/data/tracker/org.gnome.Nautilus.domain.rule.in @@ -0,0 +1,21 @@ +# This defines a private Tracker domain for Nautilus. +# +# It's used to run the Tracker indexer inside a Flatpak sandbox, when Nautilus +# is running on a host that doesn't have a suitable version of Tracker +# installed. + +[DomainOntology] +# Location for the Tracker database +CacheLocation=$XDG_CACHE_HOME/nautilus/miner/files + +# Name of the ontology to use, must be one located in +# $(sharedir)/tracker/ontologies +OntologyName=nepomuk + +# DBus name for the owner (not optional). Tracker will use +# the domain as the prefix of the DBus name for all the +# services related to this domain ontology. +Domain=@application_id@ + +# List of miners we expect to run in this domain. +Miners=Miner.Files;Miner.Extract diff --git a/meson.build b/meson.build index bb36b8a20..c33c0c5e7 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project('nautilus', 'c', # * Update GTK-based codes over src/gtk/gtk-code-generator.sh version: '3.37.91', - meson_version: '>= 0.47.0', + meson_version: '>= 0.49.0', license: 'GPL3+' ) diff --git a/src/nautilus-batch-rename-utilities.c b/src/nautilus-batch-rename-utilities.c index b6cea25fa..0412a172e 100644 --- a/src/nautilus-batch-rename-utilities.c +++ b/src/nautilus-batch-rename-utilities.c @@ -19,6 +19,7 @@ #include "nautilus-batch-rename-dialog.h" #include "nautilus-batch-rename-utilities.h" #include "nautilus-file.h" +#include "nautilus-tracker-utilities.h" #include #include @@ -63,8 +64,6 @@ enum ALBUM_NAME_INDEX, } QueryMetadata; -#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files" - static void on_cursor_callback (GObject *object, GAsyncResult *result, gpointer user_data); @@ -1119,7 +1118,7 @@ check_metadata_for_selection (NautilusBatchRenameDialog *dialog, g_string_append (query, "} ORDER BY ASC(nie:contentCreated(?content))"); - connection = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME, NULL, NULL, &error); + connection = nautilus_tracker_get_miner_fs_connection (&error); if (!connection) { if (error) diff --git a/src/nautilus-search-engine-tracker.c b/src/nautilus-search-engine-tracker.c index dde3cab26..a0e0d638c 100644 --- a/src/nautilus-search-engine-tracker.c +++ b/src/nautilus-search-engine-tracker.c @@ -25,6 +25,7 @@ #include "nautilus-search-engine-private.h" #include "nautilus-search-hit.h" #include "nautilus-search-provider.h" +#include "nautilus-tracker-utilities.h" #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH #include "nautilus-debug.h" @@ -55,8 +56,6 @@ enum LAST_PROP }; -#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files" - static void nautilus_search_provider_init (NautilusSearchProviderInterface *iface); G_DEFINE_TYPE_WITH_CODE (NautilusSearchEngineTracker, @@ -79,8 +78,9 @@ finalize (GObject *object) } g_clear_object (&tracker->query); - g_clear_object (&tracker->connection); g_queue_free_full (tracker->hits_pending, g_object_unref); + /* This is a singleton, no need to unref. */ + tracker->connection = NULL; G_OBJECT_CLASS (nautilus_search_engine_tracker_parent_class)->finalize (object); } @@ -601,8 +601,7 @@ nautilus_search_engine_tracker_init (NautilusSearchEngineTracker *engine) engine->hits_pending = g_queue_new (); - engine->connection = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME, NULL, NULL, &error); - + engine->connection = nautilus_tracker_get_miner_fs_connection (&error); if (error) { g_warning ("Could not establish a connection to Tracker: %s", error->message); diff --git a/src/nautilus-tag-manager.c b/src/nautilus-tag-manager.c index 8009e6ca9..e21749a10 100644 --- a/src/nautilus-tag-manager.c +++ b/src/nautilus-tag-manager.c @@ -21,6 +21,7 @@ #include "nautilus-file.h" #include "nautilus-file-undo-operations.h" #include "nautilus-file-undo-manager.h" +#include "nautilus-tracker-utilities.h" #define DEBUG_FLAG NAUTILUS_DEBUG_TAG_MANAGER #include "nautilus-debug.h" @@ -35,6 +36,7 @@ struct _NautilusTagManager gboolean tracker_ok; TrackerSparqlConnection *local; TrackerSparqlConnection *miner_fs; + const gchar *miner_fs_busname; TrackerNotifier *notifier; TrackerSparqlStatement *query_starred_files; @@ -81,14 +83,12 @@ enum LAST_SIGNAL }; -#define TRACKER_MINER_FS_BUSNAME "org.freedesktop.Tracker3.Miner.Files" - #define QUERY_STARRED_FILES \ "SELECT ?file_url ?content_id " \ "{ " \ " ?content_urn a nautilus:FileReference ; " \ " nautilus:starred true . " \ - " SERVICE { " \ + " SERVICE { " \ " ?content_urn nie:isStoredAs ?file_url . " \ " BIND (tracker:id (?content_urn) AS ?content_id) " \ " } " \ @@ -97,7 +97,7 @@ enum #define QUERY_UPDATED_FILE_URL \ "SELECT ?file_url EXISTS { ?content_urn nautilus:starred true } AS ?starred" \ "{ " \ - " SERVICE { " \ + " SERVICE { " \ " ?content_urn nie:isStoredAs ?file_url . " \ " FILTER (tracker:id(?content_urn) = ~id) " \ " }" \ @@ -432,14 +432,15 @@ nautilus_tag_manager_delete_tag (NautilusTagManager *self, GList *selection, GString *query) { - g_string_append (query, - "DELETE { " - " ?content_urn a nautilus:FileReference ; " - " nautilus:starred true . " - "} " - "WHERE { " - " SERVICE { " - " ?content_urn nie:isStoredAs ?file_url . "); + g_string_append_printf (query, + "DELETE { " + " ?content_urn a nautilus:FileReference ; " + " nautilus:starred true . " + "} " + "WHERE { " + " SERVICE { " + " ?content_urn nie:isStoredAs ?file_url . ", + self->miner_fs_busname); query = add_selection_filter (selection, query); @@ -453,13 +454,14 @@ nautilus_tag_manager_insert_tag (NautilusTagManager *self, GList *selection, GString *query) { - g_string_append (query, - "INSERT { " - " ?content_urn a nautilus:FileReference . " - " ?content_urn nautilus:starred true . " - "} WHERE { " - " SERVICE { " - " ?content_urn nie:isStoredAs ?file_url . "); + g_string_append_printf (query, + "INSERT { " + " ?content_urn a nautilus:FileReference . " + " ?content_urn nautilus:starred true . " + "} WHERE { " + " SERVICE { " + " ?content_urn nie:isStoredAs ?file_url . ", + self->miner_fs_busname); query = add_selection_filter (selection, query); @@ -570,11 +572,13 @@ nautilus_tag_manager_get_file_ids_for_urls (NautilusTagManager *self, { GString *query; - query = g_string_new ("SELECT ?file_url ?content_id " - "WHERE { " - " SERVICE { " - " ?content_urn nie:isStoredAs ?file_url . " - " BIND (tracker:id (?content_urn) AS ?content_id) "); + query = g_string_new (""); + g_string_append_printf (query, "SELECT ?file_url ?content_id " + "WHERE { " + " SERVICE { " + " ?content_urn nie:isStoredAs ?file_url . " + " BIND (tracker:id (?content_urn) AS ?content_id) ", + self->miner_fs_busname); query = add_selection_filter (selection, query); @@ -890,6 +894,7 @@ setup_tracker_connections (NautilusTagManager *self, GError **error) { const gchar *datadir; + gchar *query_with_busname; g_autofree gchar *store_path = NULL; g_autofree gchar *ontology_path = NULL; g_autoptr (GFile) store = NULL; @@ -917,31 +922,32 @@ setup_tracker_connections (NautilusTagManager *self, } /* Connect to Tracker filesystem index to follow file renames. */ - self->miner_fs = tracker_sparql_connection_bus_new (TRACKER_MINER_FS_BUSNAME, - NULL, - NULL, - error); - + self->miner_fs = nautilus_tracker_get_miner_fs_connection (error); if (*error) { return FALSE; } + self->miner_fs_busname = nautilus_tracker_get_miner_fs_busname (NULL); /* Prepare reusable queries. */ + query_with_busname = g_strdup_printf (QUERY_UPDATED_FILE_URL, self->miner_fs_busname); self->query_updated_file_url = tracker_sparql_connection_query_statement (self->local, - QUERY_UPDATED_FILE_URL, + query_with_busname, cancellable, error); + g_free (query_with_busname); if (*error) { return FALSE; } + query_with_busname = g_strdup_printf (QUERY_STARRED_FILES, self->miner_fs_busname); self->query_starred_files = tracker_sparql_connection_query_statement (self->local, - QUERY_STARRED_FILES, + query_with_busname, cancellable, error); + g_free (query_with_busname); if (*error) { diff --git a/src/nautilus-tracker-utilities.c b/src/nautilus-tracker-utilities.c index b220df4bd..4c408942e 100644 --- a/src/nautilus-tracker-utilities.c +++ b/src/nautilus-tracker-utilities.c @@ -18,12 +18,132 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#include "config.h" #include "nautilus-tracker-utilities.h" #include "nautilus-global-preferences.h" #define TRACKER_KEY_RECURSIVE_DIRECTORIES "index-recursive-directories" #define TRACKER_KEY_SINGLE_DIRECTORIES "index-single-directories" +/* Shared global connection to Tracker Miner FS */ +static const gchar *tracker_miner_fs_busname = NULL; +static TrackerSparqlConnection *tracker_miner_fs_connection = NULL; +static GError *tracker_miner_fs_error = NULL; + +static gboolean +get_host_tracker_miner_fs (GError **error) +{ + const gchar *busname = "org.freedesktop.Tracker3.Miner.Files"; + + g_message ("Connecting to %s", busname); + tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error); + if (*error) + { + g_warning ("Unable to create connection for session-wide Tracker indexer: %s", (*error)->message); + return FALSE; + } + + tracker_miner_fs_busname = busname; + return TRUE; +} + +static gboolean +start_local_tracker_miner_fs (GError **error) +{ + const gchar *busname = APPLICATION_ID ".Tracker3.Miner.Files"; + + g_message ("Starting %s", busname); + tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error); + if (*error) + { + g_critical ("Could not start local Tracker indexer at %s: %s", busname, (*error)->message); + return FALSE; + } + + tracker_miner_fs_busname = busname; + return TRUE; +} + +static gboolean +inside_flatpak (void) +{ + return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS); +} + +static void +setup_tracker_miner_fs_connection (void) +{ + static gsize tried_tracker_init = FALSE; + + if (g_once_init_enter (&tried_tracker_init)) + { + gboolean success; + + success = get_host_tracker_miner_fs (&tracker_miner_fs_error); + + if (!success && inside_flatpak ()) + { + g_clear_error (&tracker_miner_fs_error); + success = start_local_tracker_miner_fs (&tracker_miner_fs_error); + } + + g_once_init_leave (&tried_tracker_init, TRUE); + } +} + +/** + * nautilus_tracker_get_miner_fs_connection: + * @error: return location for a #GError + * + * This function returns a global singleton #TrackerSparqlConnection, or %NULL + * if we couldn't connect to Tracker Miner FS. + * + * The first time you call it, this function will block while trying to connect. + * This may take some time if starting Tracker Miners from a Flatpak bundle. + * + * The returned object is a globally shared singleton which should NOT be + * unreffed. + * + * Returns: a #TrackerSparqlConnection, or %NULL + */ +TrackerSparqlConnection * +nautilus_tracker_get_miner_fs_connection (GError **error) +{ + setup_tracker_miner_fs_connection (); + + if (tracker_miner_fs_error && error) + { + *error = g_error_copy (tracker_miner_fs_error); + } + + return tracker_miner_fs_connection; +} + +/** + * nautilus_tracker_get_miner_fs_busname: + * @error: return location for a #GError + * + * This function returns a DBus name that can be used to talk to + * tracker-miner-fs, or %NULL if there is no Tracker Miner FS available. + * + * The first time you call it, this function will block while trying to connect. + * This may take some time if starting Tracker Miners from a Flatpak bundle. + * + * Returns: a string + */ +const gchar * +nautilus_tracker_get_miner_fs_busname (GError **error) +{ + setup_tracker_miner_fs_connection (); + + if (tracker_miner_fs_error && error) + { + *error = g_error_copy (tracker_miner_fs_error); + } + + return tracker_miner_fs_busname; +} + static GFile * location_from_tracker_dir (const gchar *value) { diff --git a/src/nautilus-tracker-utilities.h b/src/nautilus-tracker-utilities.h index f509c3005..d4b2eba0c 100644 --- a/src/nautilus-tracker-utilities.h +++ b/src/nautilus-tracker-utilities.h @@ -22,5 +22,9 @@ #pragma once #include +#include -gboolean nautilus_tracker_directory_is_tracked (GFile *directory); +TrackerSparqlConnection * nautilus_tracker_get_miner_fs_connection (GError **error); +const gchar * nautilus_tracker_get_miner_fs_busname (GError **error); + +gboolean nautilus_tracker_directory_is_tracked (GFile *directory); -- cgit v1.2.1