[tracker/wip/carlosg/transact-graphs: 4/4] libtracker-data: Handle graph updates after commit as a transaction
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/transact-graphs: 4/4] libtracker-data: Handle graph updates after commit as a transaction
- Date: Sun, 23 Aug 2020 21:57:12 +0000 (UTC)
commit 93951368fc7878b21284722bd17269ceea325404
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Aug 23 21:47:15 2020 +0200
libtracker-data: Handle graph updates after commit as a transaction
After a graph is created/deleted, we update immediately our graph
accounting. This however didn't take into account that graph operations
may happen within a transaction, so a readonly interface being spawned
at the right time might consider those graphs as existing its query even
though they are not attached yet.
This situation would resolve itself after the last graph is processed,
and the transaction committed, but for that query it would fail like:
In service 'dbus:org.freedesktop.Tracker3.Miner.Files': no such table:
http://tracker.api.gnome.org/ontology/v3/tracker#Audio.nfo:Audio
In order to fix that, handle changes to the known graphs as part of the
transaction, only making it effective after the change is committed, and
database interfaces would correctly find the graph databases when updated.
This makes readonly interfaces aware of the graph changes after the
transaction is committed, not before.
When looking up graphs, it depends on whether the sparql is being executed
on the update queue or not that it makes sense to return results from the
graph state mid-transaction or not. Do this based on the TrackerSparql query
type.
Of course, this means the operation should be rolled back if the
transaction failed. Also do that.
Fixes: https://gitlab.gnome.org/GNOME/tracker/-/issues/231
src/libtracker-data/tracker-data-manager.c | 63 ++++++++++++++++++++++++++----
src/libtracker-data/tracker-data-manager.h | 8 +++-
src/libtracker-data/tracker-data-update.c | 9 ++++-
src/libtracker-data/tracker-sparql.c | 11 +++++-
4 files changed, 78 insertions(+), 13 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 47d721954..fd02de2a8 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -80,6 +80,7 @@ struct _TrackerDataManager {
TrackerOntologies *ontologies;
TrackerData *data_update;
+ GHashTable *transaction_graphs;
GHashTable *graphs;
gchar *status;
@@ -198,8 +199,12 @@ tracker_data_manager_ensure_graphs (TrackerDataManager *manager,
}
GHashTable *
-tracker_data_manager_get_graphs (TrackerDataManager *manager)
+tracker_data_manager_get_graphs (TrackerDataManager *manager,
+ gboolean in_transaction)
{
+ if (manager->transaction_graphs && in_transaction)
+ return manager->transaction_graphs;
+
return manager->graphs;
}
@@ -4827,6 +4832,25 @@ tracker_data_manager_get_namespaces (TrackerDataManager *manager)
return ht;
}
+static GHashTable *
+copy_graphs (GHashTable *graphs)
+{
+ GHashTable *copy;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ copy = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+ g_hash_table_iter_init (&iter, graphs);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ g_hash_table_insert (copy, g_strdup (key), value);
+
+ return copy;
+}
+
gboolean
tracker_data_manager_create_graph (TrackerDataManager *manager,
const gchar *name,
@@ -4852,9 +4876,10 @@ tracker_data_manager_create_graph (TrackerDataManager *manager,
if (id == 0)
goto detach;
- g_hash_table_insert (manager->graphs, g_strdup (name), GINT_TO_POINTER (id));
+ if (!manager->transaction_graphs)
+ manager->transaction_graphs = copy_graphs (manager->graphs);
- manager->generation++;
+ g_hash_table_insert (manager->transaction_graphs, g_strdup (name), GINT_TO_POINTER (id));
return TRUE;
@@ -4887,22 +4912,29 @@ tracker_data_manager_drop_graph (TrackerDataManager *manager,
if (!tracker_data_delete_graph (manager->data_update, name, error))
return FALSE;
- manager->generation++;
+ if (!manager->transaction_graphs)
+ manager->transaction_graphs = copy_graphs (manager->graphs);
- if (manager->graphs)
- g_hash_table_remove (manager->graphs, name);
+ g_hash_table_remove (manager->transaction_graphs, name);
return TRUE;
}
gint
tracker_data_manager_find_graph (TrackerDataManager *manager,
- const gchar *name)
+ const gchar *name,
+ gboolean in_transaction)
{
TrackerDBInterface *iface;
GHashTable *graphs;
iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+
+ if (in_transaction && manager->transaction_graphs) {
+ return GPOINTER_TO_INT (g_hash_table_lookup (manager->transaction_graphs,
+ name));
+ }
+
graphs = tracker_data_manager_ensure_graphs (manager, iface, NULL);
if (!graphs)
@@ -5053,3 +5085,20 @@ tracker_data_manager_get_generation (TrackerDataManager *manager)
{
return manager->generation;
}
+
+void
+tracker_data_manager_commit_graphs (TrackerDataManager *manager)
+{
+ if (manager->transaction_graphs) {
+ g_clear_pointer (&manager->graphs, g_hash_table_unref);
+ manager->graphs = manager->transaction_graphs;
+ manager->transaction_graphs = NULL;
+ manager->generation++;
+ }
+}
+
+void
+tracker_data_manager_rollback_graphs (TrackerDataManager *manager)
+{
+ g_clear_pointer (&manager->transaction_graphs, g_hash_table_unref);
+}
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index b7572e6d4..dbd4d86fc 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -94,12 +94,16 @@ gboolean tracker_data_manager_copy_graph (TrackerDataManager *mana
const gchar *destination,
GError **error);
-GHashTable * tracker_data_manager_get_graphs (TrackerDataManager *manager);
+GHashTable * tracker_data_manager_get_graphs (TrackerDataManager *manager,
+ gboolean in_transaction);
gint tracker_data_manager_find_graph (TrackerDataManager *manager,
- const gchar *name);
+ const gchar *name,
+ gboolean in_transaction);
guint tracker_data_manager_get_generation (TrackerDataManager *manager);
+void tracker_data_manager_rollback_graphs (TrackerDataManager *manager);
+void tracker_data_manager_commit_graphs (TrackerDataManager *manager);
G_END_DECLS
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index abc51860a..86a707dde 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -2014,7 +2014,7 @@ ensure_graph_buffer (TrackerDataUpdateBuffer *buffer,
return graph_buffer;
}
- if (name && !tracker_data_manager_find_graph (data->manager, name)) {
+ if (name && !tracker_data_manager_find_graph (data->manager, name, TRUE)) {
if (!tracker_data_manager_create_graph (data->manager, name, error))
return NULL;
}
@@ -2023,7 +2023,8 @@ ensure_graph_buffer (TrackerDataUpdateBuffer *buffer,
graph_buffer->graph = g_strdup (name);
if (graph_buffer->graph) {
graph_buffer->id = tracker_data_manager_find_graph (data->manager,
- graph_buffer->graph);
+ graph_buffer->graph,
+ TRUE);
}
graph_buffer->resources =
@@ -2562,6 +2563,8 @@ tracker_data_commit_transaction (TrackerData *data,
data->update_buffer.fts_ever_updated = FALSE;
}
+ tracker_data_manager_commit_graphs (data->manager);
+
tracker_db_interface_execute_query (iface, NULL, "PRAGMA cache_size = %d",
TRACKER_DB_CACHE_SIZE_DEFAULT);
g_ptr_array_set_size (data->update_buffer.graphs, 0);
@@ -2592,6 +2595,8 @@ tracker_data_rollback_transaction (TrackerData *data)
g_clear_error (&ignorable);
}
+ tracker_data_manager_rollback_graphs (data->manager);
+
tracker_db_interface_execute_query (iface, NULL, "PRAGMA cache_size = %d",
TRACKER_DB_CACHE_SIZE_DEFAULT);
tracker_data_dispatch_rollback_statement_callbacks (data);
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 4b8e16534..01515849e 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -688,8 +688,11 @@ static GHashTable *
tracker_sparql_get_effective_graphs (TrackerSparql *sparql)
{
GHashTable *graphs;
+ gboolean in_transaction;
- graphs = tracker_data_manager_get_graphs (sparql->data_manager);
+ in_transaction = sparql->query_type == TRACKER_SPARQL_QUERY_UPDATE;
+ graphs = tracker_data_manager_get_graphs (sparql->data_manager,
+ in_transaction);
if (graphs && sparql->policy.graphs) {
if (!sparql->policy.filtered_graphs) {
@@ -835,6 +838,7 @@ tracker_sparql_find_graph (TrackerSparql *sparql,
const gchar *name)
{
GHashTable *effective_graphs;
+ gboolean in_transaction;
effective_graphs = tracker_sparql_get_effective_graphs (sparql);
if (!effective_graphs ||
@@ -842,7 +846,10 @@ tracker_sparql_find_graph (TrackerSparql *sparql,
return 0;
}
- return tracker_data_manager_find_graph (sparql->data_manager, name);
+ in_transaction = sparql->query_type == TRACKER_SPARQL_QUERY_UPDATE;
+
+ return tracker_data_manager_find_graph (sparql->data_manager, name,
+ in_transaction);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]