[tracker/wip/carlosg/wal-and-other-fixes: 8/8] libtracker-data: Create graph databases with a separate interface
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/wal-and-other-fixes: 8/8] libtracker-data: Create graph databases with a separate interface
- Date: Wed, 1 Jul 2020 17:40:25 +0000 (UTC)
commit f3bb1b11dc677d1bad40c0807e7e2cb4006c1803
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Jul 1 18:51:04 2020 +0200
libtracker-data: Create graph databases with a separate interface
Due to the way we create graphs (either implicitly on updates, or
via a CREATE GRAPH update), those always happen inside a DB
transaction, whereas WAL is documented to be ineffective (immediately
at least) if set inside a transaction.
This leaves freshly created database connections running on the
"delete" journal mode, even though WAL is "set", and would eventually
apply the next time the database is opened. This journal mode has
many drawbacks (worse performance, readers and writers possibly stalling
each other, ...) that are noticeable on eg. first index.
To fix this, delegate database file construction to a separate writable
interface created exclusively for this task, the WAL journal mode and
page size will be set there, so it is ensured to open with the right
journal mode when we open it with the readwrite interface.
Immediate benefits:
- First time tracker-miner-fs indexing (not involving tracker-extract)
went locally from ~15s to ~9s, much closer to 2.x performance.
- Select queries won't stall, hopefully fixes some of those weird timeouts
we've been seeing.
src/libtracker-data/tracker-db-manager.c | 52 +++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 11 deletions(-)
---
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 08ab085bf..6b3c4bdd7 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -1000,6 +1000,44 @@ tracker_db_manager_check_perform_vacuum (TrackerDBManager *db_manager)
tracker_db_interface_execute_query (iface, NULL, "VACUUM");
}
+static gboolean
+ensure_create_database_file (TrackerDBManager *db_manager,
+ GFile *file,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ GError *file_error = NULL;
+ gchar *path;
+
+ /* Ensure the database is created from scratch */
+ if (!g_file_delete (file, NULL, &file_error)) {
+ if (!g_error_matches (file_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+ g_propagate_error (error, file_error);
+ return FALSE;
+ }
+
+ g_clear_error (&file_error);
+ }
+
+ /* Create the database file in a separate interface, so we can
+ * configure page_size and journal_mode outside a transaction, so
+ * they apply throughout the whole lifetime.
+ */
+ path = g_file_get_path (file);
+ iface = tracker_db_interface_sqlite_new (path,
+ db_manager->shared_cache_key,
+ 0, error);
+ if (!iface)
+ return FALSE;
+
+ tracker_db_interface_execute_query (iface, NULL, "PRAGMA cache_size = %d",
+ db_manager->db.page_size);
+ tracker_db_interface_execute_query (iface, NULL, "PRAGMA journal_mode = WAL");
+
+ g_object_unref (iface);
+ return TRUE;
+}
+
gboolean
tracker_db_manager_attach_database (TrackerDBManager *db_manager,
TrackerDBInterface *iface,
@@ -1018,17 +1056,9 @@ tracker_db_manager_attach_database (TrackerDBManager *db_manager,
g_free (escaped);
if (create) {
- GError *inner_error = NULL;
-
- /* Create the database from scratch */
- if (!g_file_delete (file, NULL, &inner_error)) {
- if (!g_error_matches (inner_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
- g_object_unref (file);
- g_propagate_error (error, inner_error);
- return FALSE;
- }
-
- g_clear_error (&inner_error);
+ if (!ensure_create_database_file (db_manager, file, error)) {
+ g_object_unref (file);
+ return FALSE;
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]