From 9e9a34fe232d222dd67aa6d3abdf23ee3310bf95 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 28 Nov 2020 19:48:02 +0100 Subject: libtracker-data: Add fast path to insert new bnode UUIDs The way to insert bnodes used to consist of 1) SELECT SparqlBNode() (which may query multiple times for an unused one). 2) SELECT ID FROM Resource WHERE Uri=bnode 3) INSERT INTO Resource(..., bnode) Step 2 no longer applies since earlier commits, but this can be streamlined so we try to insert bnodes until one comes up successful, and it'll usually be on the first try. Make this apply to direct updates from TrackerResource, as that's where it's easiest to pull off. --- src/libtracker-data/tracker-data-update.c | 61 +++++++++++++++++++++++++++++-- src/libtracker-data/tracker-data-update.h | 3 ++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c index 0f865f0a2..fcce6d105 100644 --- a/src/libtracker-data/tracker-data-update.c +++ b/src/libtracker-data/tracker-data-update.c @@ -37,6 +37,7 @@ #include "tracker-property.h" #include "tracker-sparql.h" #include "tracker-turtle-reader.h" +#include "tracker-uuid.h" typedef struct _TrackerDataUpdateBuffer TrackerDataUpdateBuffer; typedef struct _TrackerDataUpdateBufferGraph TrackerDataUpdateBufferGraph; @@ -1578,8 +1579,7 @@ get_bnode_for_resource (GHashTable *bnodes, return bnode; iface = tracker_data_manager_get_writable_db_interface (data->manager); - bnode = tracker_data_query_unused_uuid (data->manager, - iface); + bnode = tracker_data_update_ensure_new_bnode (data, iface, NULL); identifier = tracker_resource_get_identifier (resource); g_hash_table_insert (bnodes, g_strdup (identifier), bnode); @@ -1627,8 +1627,7 @@ bytes_from_gvalue (GValue *gvalue, TrackerDBInterface *iface; iface = tracker_data_manager_get_writable_db_interface (data->manager); - bnode = tracker_data_query_unused_uuid (data->manager, - iface); + bnode = tracker_data_update_ensure_new_bnode (data, iface, NULL); g_hash_table_insert (bnodes, g_strdup (uri), bnode); } @@ -3063,3 +3062,57 @@ tracker_data_update_resource (TrackerData *data, return retval; } + +gchar * +tracker_data_update_ensure_new_bnode (TrackerData *data, + TrackerDBInterface *iface, + GError **error) +{ + TrackerDBStatement *stmt = NULL; + GError *inner_error = NULL; + gchar *uuid, *key; + gint id; + + iface = tracker_data_manager_get_writable_db_interface (data->manager); + + stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, + &inner_error, + "INSERT INTO Resource (Uri, BlankNode) VALUES (?, ?)"); + if (!stmt) { + g_propagate_error (error, inner_error); + return NULL; + } + + while (TRUE) { + uuid = tracker_generate_uuid ("urn:bnode:"); + + tracker_db_statement_bind_text (stmt, 0, uuid); + tracker_db_statement_bind_int (stmt, 1, 1); + tracker_db_statement_execute (stmt, &inner_error); + + if (!inner_error || + !g_error_matches (inner_error, + TRACKER_DB_INTERFACE_ERROR, + TRACKER_DB_CONSTRAINT)) { + break; + } + + /* Constraint error, retry */ + g_clear_error (&inner_error); + g_free (uuid); + } + + g_object_unref (stmt); + + if (inner_error) { + g_propagate_error (error, inner_error); + return NULL; + } + + id = tracker_db_interface_sqlite_get_last_insert_id (iface); + key = g_strdup (uuid); + g_hash_table_insert (data->update_buffer.resource_cache, key, GINT_TO_POINTER (id)); + g_hash_table_add (data->update_buffer.new_resources, key); + + return uuid; +} diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h index 21d6d89e9..8df34e213 100644 --- a/src/libtracker-data/tracker-data-update.h +++ b/src/libtracker-data/tracker-data-update.h @@ -146,6 +146,9 @@ gboolean tracker_data_update_resource (TrackerData *data, gint tracker_data_update_ensure_resource (TrackerData *data, const gchar *uri, gboolean *create); +gchar * tracker_data_update_ensure_new_bnode (TrackerData *data, + TrackerDBInterface *iface, + GError **error); GType tracker_data_get_type (void) G_GNUC_CONST; TrackerData * tracker_data_new (TrackerDataManager *manager); -- cgit v1.2.1