diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2018-11-13 12:23:30 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2018-11-13 12:23:30 +0100 |
commit | 6c5a3fa52fee5779a3a286896f032c50e5b446ff (patch) | |
tree | 228b33696d190558c089b0535b81ac7fa3c0afcf | |
parent | eb82efe8dacdca2b283264c52286244a01682e73 (diff) | |
parent | efd69c3629952931e4ec255a494d025eccb9769d (diff) | |
download | tracker-6c5a3fa52fee5779a3a286896f032c50e5b446ff.tar.gz |
Merge branch 'wip/carlosg/automatic-store-shutdown'
-rw-r--r-- | src/libtracker-bus/tracker-bus.vala | 16 | ||||
-rw-r--r-- | src/libtracker-miner/tracker-miner-proxy.c | 68 | ||||
-rw-r--r-- | src/libtracker-sparql-backend/tracker-backend.vala | 18 | ||||
-rw-r--r-- | src/tracker-store/tracker-main.vala | 32 | ||||
-rw-r--r-- | src/tracker-store/tracker-store.vala | 59 | ||||
-rw-r--r-- | tests/functional-tests/ipc/test-bus-query.vala | 2 | ||||
-rw-r--r-- | tests/functional-tests/ipc/test-bus-update.vala | 2 |
7 files changed, 105 insertions, 92 deletions
diff --git a/src/libtracker-bus/tracker-bus.vala b/src/libtracker-bus/tracker-bus.vala index 3b971d030..a257c51c8 100644 --- a/src/libtracker-bus/tracker-bus.vala +++ b/src/libtracker-bus/tracker-bus.vala @@ -21,7 +21,7 @@ public class Tracker.Bus.Connection : Tracker.Sparql.Connection { DBusConnection bus; string dbus_name; - public Connection (string dbus_name, DBusConnection? dbus_connection) throws Sparql.Error, IOError, DBusError, GLib.Error { + public Connection (string dbus_name, DBusConnection? dbus_connection, bool start) throws Sparql.Error, IOError, DBusError, GLib.Error { this.dbus_name = dbus_name; if (dbus_connection == null) @@ -29,14 +29,16 @@ public class Tracker.Bus.Connection : Tracker.Sparql.Connection { else bus = dbus_connection; - debug ("Waiting for service to become available..."); + if (start) { + debug ("Waiting for service to become available..."); - // do not use proxy to work around race condition in GDBus - // NB#259760 - var msg = new DBusMessage.method_call (dbus_name, Tracker.DBUS_OBJECT_STATUS, Tracker.DBUS_INTERFACE_STATUS, "Wait"); - bus.send_message_with_reply_sync (msg, 0, /* timeout */ int.MAX, null).to_gerror (); + // do not use proxy to work around race condition in GDBus + // NB#259760 + var msg = new DBusMessage.method_call (dbus_name, Tracker.DBUS_OBJECT_STATUS, Tracker.DBUS_INTERFACE_STATUS, "Wait"); + bus.send_message_with_reply_sync (msg, 0, /* timeout */ int.MAX, null).to_gerror (); - debug ("Service is ready"); + debug ("Service is ready"); + } // ensure that error domain is registered with GDBus new Sparql.Error.INTERNAL (""); diff --git a/src/libtracker-miner/tracker-miner-proxy.c b/src/libtracker-miner/tracker-miner-proxy.c index 0e47395aa..465d6103c 100644 --- a/src/libtracker-miner/tracker-miner-proxy.c +++ b/src/libtracker-miner/tracker-miner-proxy.c @@ -51,9 +51,7 @@ typedef struct { GDBusNodeInfo *introspection_data; gchar *dbus_path; guint registration_id; - guint watch_name_id; GHashTable *pauses; - gint availability_cookie; } TrackerMinerProxyPrivate; typedef struct { @@ -222,10 +220,6 @@ tracker_miner_proxy_finalize (GObject *object) g_free (priv->dbus_path); g_hash_table_unref (priv->pauses); - if (priv->watch_name_id != 0) { - g_bus_unwatch_name (priv->watch_name_id); - } - if (priv->registration_id != 0) { g_dbus_connection_unregister_object (priv->d_connection, priv->registration_id); @@ -732,55 +726,6 @@ miner_progress_cb (TrackerMiner *miner, emit_dbus_signal (proxy, "Progress", variant); } -static void -on_tracker_store_appeared (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) - -{ - TrackerMinerProxy *proxy = user_data; - TrackerMinerProxyPrivate *priv = tracker_miner_proxy_get_instance_private (proxy); - - g_debug ("Miner:'%s' noticed store availability has changed to AVAILABLE", - priv->dbus_path); - - if (priv->availability_cookie != 0) { - g_hash_table_remove (priv->pauses, - GINT_TO_POINTER (priv->availability_cookie)); - sync_miner_pause_state (proxy); - priv->availability_cookie = 0; - } -} - -static void -on_tracker_store_disappeared (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - TrackerMinerProxy *proxy = user_data; - TrackerMinerProxyPrivate *priv = tracker_miner_proxy_get_instance_private (proxy); - - g_debug ("Miner:'%s' noticed store availability has changed to UNAVAILABLE", - priv->dbus_path); - - if (priv->availability_cookie == 0) { - GError *error = NULL; - gint cookie_id; - - cookie_id = pause_miner (proxy, NULL, - _("Data store is not available"), - NULL, &error); - - if (error) { - g_warning ("Could not pause, %s", error->message); - g_error_free (error); - } else { - priv->availability_cookie = cookie_id; - } - } -} - static gboolean tracker_miner_proxy_initable_init (GInitable *initable, GCancellable *cancellable, @@ -790,7 +735,6 @@ tracker_miner_proxy_initable_init (GInitable *initable, TrackerMinerProxyPrivate *priv = tracker_miner_proxy_get_instance_private (proxy); GError *inner_error = NULL; TrackerDomainOntology *domain_ontology; - gchar *store_name; GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, @@ -824,18 +768,6 @@ tracker_miner_proxy_initable_init (GInitable *initable, return FALSE; } - store_name = tracker_domain_ontology_get_domain (domain_ontology, "Tracker1"); - - priv->watch_name_id = - g_bus_watch_name_on_connection (priv->d_connection, - store_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - on_tracker_store_appeared, - on_tracker_store_disappeared, - proxy, - NULL); - g_free (store_name); - g_signal_connect (priv->miner, "started", G_CALLBACK (miner_started_cb), proxy); g_signal_connect (priv->miner, "stopped", diff --git a/src/libtracker-sparql-backend/tracker-backend.vala b/src/libtracker-sparql-backend/tracker-backend.vala index d99ceb291..db822dc51 100644 --- a/src/libtracker-sparql-backend/tracker-backend.vala +++ b/src/libtracker-sparql-backend/tracker-backend.vala @@ -203,12 +203,22 @@ class Tracker.Sparql.Backend : Connection { switch (backend) { case Backend.AUTO: - bus = new Tracker.Bus.Connection (domain_ontology.get_domain ("Tracker1"), global_dbus_connection); + bool direct_failed = false; try { direct = create_readonly_direct (); - } catch (GLib.Error e) { - warning ("Falling back to bus backend, the direct backend failed to initialize: " + e.message); + } catch (DBInterfaceError e) { + direct_failed = true; + } + + bus = new Tracker.Bus.Connection (domain_ontology.get_domain ("Tracker1"), global_dbus_connection, direct_failed); + + if (direct_failed) { + try { + direct = create_readonly_direct (); + } catch (DBInterfaceError e) { + warning ("Falling back to bus backend, the direct backend failed to initialize: " + e.message); + } } break; @@ -218,7 +228,7 @@ class Tracker.Sparql.Backend : Connection { break; case Backend.BUS: - bus = new Tracker.Bus.Connection (domain_ontology.get_domain ("Tracker1"), global_dbus_connection); + bus = new Tracker.Bus.Connection (domain_ontology.get_domain ("Tracker1"), global_dbus_connection, false); break; default: diff --git a/src/tracker-store/tracker-main.vala b/src/tracker-store/tracker-main.vala index 478076278..1e8d1ddd2 100644 --- a/src/tracker-store/tracker-main.vala +++ b/src/tracker-store/tracker-main.vala @@ -37,6 +37,7 @@ License which can be viewed at: static MainLoop main_loop; static string log_filename; + static uint shutdown_timeout_id; static bool shutdown; static Tracker.Direct.Connection connection; @@ -52,11 +53,13 @@ License which can be viewed at: static File data_location; static File ontology_location; static string domain; + static bool disable_shutdown; const OptionEntry entries[] = { /* Daemon options */ { "version", 'V', 0, OptionArg.NONE, ref version, N_("Displays version information"), null }, { "verbosity", 'v', 0, OptionArg.INT, ref verbosity, N_("Logging, 0 = errors only, 1 = minimal, 2 = detailed and 3 = debug (default = 0)"), null }, + { "disable-shutdown", 's', 0, OptionArg.NONE, ref disable_shutdown, N_("Disable automatic shutdown"), null }, /* Indexer options */ { "force-reindex", 'r', 0, OptionArg.NONE, ref force_reindex, N_("Force a re-index of all content"), null }, @@ -180,6 +183,33 @@ License which can be viewed at: return connection; } + private static bool shutdown_timeout () { + message ("Store shutting down after timeout"); + do_shutdown (); + return GLib.Source.REMOVE; + } + + private static void idle_cb () { + /* Do not perform shutdown in case of exotic buses */ + if (Tracker.IPC.bus () != GLib.BusType.SESSION) + return; + if (shutdown_timeout_id != 0) + return; + if (disable_shutdown) + return; + + message ("Store is idle, setting shutdown timeout"); + shutdown_timeout_id = GLib.Timeout.add_seconds (30, shutdown_timeout); + } + + private static void busy_cb () { + if (shutdown_timeout_id == 0) + return; + message ("Store is busy, removing shutdown timeout"); + GLib.Source.remove (shutdown_timeout_id); + shutdown_timeout_id = 0; + } + static int main (string[] args) { Intl.setlocale (LocaleCategory.ALL, ""); @@ -265,7 +295,7 @@ License which can be viewed at: var notifier = Tracker.DBus.register_notifier (); - Tracker.Store.init (config); + Tracker.Store.init (config, idle_cb, busy_cb); /* Make Tracker available for introspection */ if (!Tracker.DBus.register_objects ()) { diff --git a/src/tracker-store/tracker-store.vala b/src/tracker-store/tracker-store.vala index 03cc8078a..f7b03a601 100644 --- a/src/tracker-store/tracker-store.vala +++ b/src/tracker-store/tracker-store.vala @@ -39,6 +39,11 @@ public class Tracker.Store { public delegate void SparqlQueryInThread (Sparql.Cursor cursor) throws Error; + public delegate void StateCallback (); + static unowned StateCallback idle_cb; + static unowned StateCallback busy_cb; + static bool busy; + class CursorTask { public Sparql.Cursor cursor; public unowned SourceFunc callback; @@ -61,11 +66,12 @@ public class Tracker.Store { Idle.add (() => { task.callback (); + update_state (); return false; }); } - public static void init (Tracker.Config config_p) { + public static void init (Tracker.Config config_p, StateCallback idle, StateCallback busy) { string max_task_time_env = Environment.get_variable ("TRACKER_STORE_MAX_TASK_TIME"); if (max_task_time_env != null) { max_task_time = int.parse (max_task_time_env); @@ -88,6 +94,9 @@ public class Tracker.Store { ThreadPool.set_max_unused_threads (2); config = config_p; + idle_cb = idle; + busy_cb = busy; + idle_cb (); } public static void shutdown () { @@ -158,30 +167,41 @@ public class Tracker.Store { // Ignore harmless error } + update_state (); + yield; if (task.error != null) throw task.error; } + private static void pre_update () { + n_updates++; + update_state (); + ensure_signal_timeout (); + } + + private static void post_update () { + n_updates--; + update_state (); + } + public static async void sparql_update (Tracker.Direct.Connection conn, string sparql, int priority, string client_id) throws Error { if (!active) throw new Sparql.Error.UNSUPPORTED ("Store is not active"); - n_updates++; - ensure_signal_timeout (); + pre_update (); var cancellable = create_cancellable (client_id); yield conn.update_async (sparql, priority, cancellable); - n_updates--; + post_update (); } public static async Variant sparql_update_blank (Tracker.Direct.Connection conn, string sparql, int priority, string client_id) throws Error { if (!active) throw new Sparql.Error.UNSUPPORTED ("Store is not active"); - n_updates++; - ensure_signal_timeout (); + pre_update (); var cancellable = create_cancellable (client_id); var nodes = yield conn.update_blank_async (sparql, priority, cancellable); - n_updates--; + post_update (); return nodes; } @@ -189,11 +209,10 @@ public class Tracker.Store { public static async void queue_turtle_import (Tracker.Direct.Connection conn, File file, string client_id) throws Error { if (!active) throw new Sparql.Error.UNSUPPORTED ("Store is not active"); - n_updates++; - ensure_signal_timeout (); + pre_update (); var cancellable = create_cancellable (client_id); yield conn.load_async (file, cancellable); - n_updates--; + post_update (); } public static void unreg_batches (string client_id) { @@ -202,6 +221,7 @@ public class Tracker.Store { if (cancellable != null) { cancellable.cancel (); client_cancellables.remove (client_id); + update_state (); } } @@ -216,10 +236,29 @@ public class Tracker.Store { Tracker.Store.active = true; } + private static void update_state () { + bool cur_busy; + + cur_busy = (!Tracker.Store.active || /* Keep busy while paused */ + n_updates != 0 || /* There are updates */ + cursor_pool.unprocessed () > 0 || /* Select cursor pool is busy */ + cursor_pool.get_num_threads () > 0); + + if (busy == cur_busy) + return; + + busy = cur_busy; + if (busy) + busy_cb (); + else + idle_cb (); + } + private static void on_statements_committed () { Tracker.Events.transact (); Tracker.Writeback.transact (); check_graph_updated_signal (); + update_state (); } private static void on_statements_rolled_back () { diff --git a/tests/functional-tests/ipc/test-bus-query.vala b/tests/functional-tests/ipc/test-bus-query.vala index 997dc9e7c..4e51a2b07 100644 --- a/tests/functional-tests/ipc/test-bus-query.vala +++ b/tests/functional-tests/ipc/test-bus-query.vala @@ -5,7 +5,7 @@ int main( string[] args ) { try { - TestApp app = new TestApp (new Tracker.Bus.Connection ("org.freedesktop.Tracker1", null)); + TestApp app = new TestApp (new Tracker.Bus.Connection ("org.freedesktop.Tracker1", null, true)); return app.run (); } catch (GLib.Error e) { diff --git a/tests/functional-tests/ipc/test-bus-update.vala b/tests/functional-tests/ipc/test-bus-update.vala index 997dc9e7c..4e51a2b07 100644 --- a/tests/functional-tests/ipc/test-bus-update.vala +++ b/tests/functional-tests/ipc/test-bus-update.vala @@ -5,7 +5,7 @@ int main( string[] args ) { try { - TestApp app = new TestApp (new Tracker.Bus.Connection ("org.freedesktop.Tracker1", null)); + TestApp app = new TestApp (new Tracker.Bus.Connection ("org.freedesktop.Tracker1", null, true)); return app.run (); } catch (GLib.Error e) { |