[tracker/wip/carlosg/sparql1.1: 17/56] libtracker-data: Handle attaching and management of "graph" databases
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql1.1: 17/56] libtracker-data: Handle attaching and management of "graph" databases
- Date: Thu, 6 Jun 2019 11:17:36 +0000 (UTC)
commit 15be25b3bea2af5a8a2fbf77c7bc8e69dbac815c
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Mar 15 00:18:51 2019 +0100
libtracker-data: Handle attaching and management of "graph" databases
src/libtracker-data/tracker-data-manager.c | 133 ++++++++++++++++++++++
src/libtracker-data/tracker-data-update.c | 60 +++++++---
src/libtracker-data/tracker-data-update.h | 7 ++
src/libtracker-data/tracker-db-interface-sqlite.c | 49 +++++++-
src/libtracker-data/tracker-db-interface-sqlite.h | 8 ++
src/libtracker-data/tracker-db-manager.c | 38 +++++++
src/libtracker-data/tracker-db-manager.h | 10 ++
7 files changed, 290 insertions(+), 15 deletions(-)
---
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 75f4bce6d..4b63137d0 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -83,6 +83,8 @@ struct _TrackerDataManager {
TrackerOntologies *ontologies;
TrackerData *data_update;
+ GHashTable *graphs;
+
gchar *status;
};
@@ -150,6 +152,49 @@ tracker_data_ontology_error_quark (void)
return g_quark_from_static_string ("tracker-data-ontology-error-quark");
}
+static GHashTable *
+tracker_data_manager_get_graphs (TrackerDataManager *manager,
+ TrackerDBInterface *iface,
+ GError **error)
+{
+ if (!manager->graphs) {
+ TrackerDBCursor *cursor = NULL;
+ TrackerDBStatement *stmt;
+
+ manager->graphs = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
error,
+ "SELECT ID, Url FROM Resource WHERE ID IN
(SELECT ID FROM Graph)");
+ if (stmt) {
+ cursor = tracker_db_statement_start_cursor (stmt, error);
+ g_object_unref (stmt);
+ }
+
+ if (cursor) {
+ while (tracker_db_cursor_iter_next (cursor, NULL, NULL)) {
+ const gchar *name;
+ gint id;
+
+ id = tracker_db_cursor_get_int (cursor, 0);
+ name = tracker_db_cursor_get_string (cursor, 1, NULL);
+
+ g_hash_table_insert (manager->graphs,
+ g_strdup (name),
+ GINT_TO_POINTER (id));
+ }
+
+ g_object_unref (cursor);
+ } else {
+ return NULL;
+ }
+ }
+
+ return manager->graphs;
+}
+
static void
handle_unsupported_ontology_change (TrackerDataManager *manager,
const gchar *ontology_path,
@@ -3909,6 +3954,7 @@ tracker_data_manager_initable_init (GInitable *initable,
TrackerDBCursor *cursor;
TrackerDBStatement *stmt;
GHashTable *ontos_table;
+ GHashTable *graphs;
GList *sorted = NULL, *l;
gint max_id = 0;
gboolean read_only;
@@ -4372,6 +4418,22 @@ tracker_data_manager_initable_init (GInitable *initable,
tracker_data_ontology_setup_db (manager, iface, "main", TRUE,
&ontology_error);
+ graphs = tracker_data_manager_get_graphs (manager, iface, &ontology_error);
+
+ if (graphs) {
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, graphs);
+
+ while (g_hash_table_iter_next (&iter, &value, NULL)) {
+ tracker_data_ontology_setup_db (manager, iface, value, TRUE,
+ &ontology_error);
+ if (ontology_error)
+ break;
+ }
+ }
+
if (!ontology_error) {
tracker_data_ontology_import_into_db (manager, iface, TRUE,
&ontology_error);
@@ -4470,6 +4532,27 @@ tracker_data_manager_initable_init (GInitable *initable,
}
}
+ graphs = tracker_data_manager_get_graphs (manager, iface, &internal_error);
+
+ if (graphs) {
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, graphs);
+
+ while (g_hash_table_iter_next (&iter, &value, NULL)) {
+ if (!tracker_db_manager_attach_database (manager->db_manager,
+ iface, value, FALSE,
+ &internal_error))
+ break;
+ }
+ }
+
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ return FALSE;
+ }
+
skip_ontology_check:
/* If locale changed, re-create indexes */
if (!read_only && tracker_db_manager_locale_changed (manager->db_manager, NULL)) {
@@ -4603,6 +4686,7 @@ tracker_data_manager_finalize (GObject *object)
g_clear_object (&manager->ontologies);
g_clear_object (&manager->data_update);
+ g_clear_pointer (&manager->graphs, g_hash_table_unref);
g_free (manager->status);
G_OBJECT_CLASS (tracker_data_manager_parent_class)->finalize (object);
@@ -4704,3 +4788,52 @@ tracker_data_manager_get_namespaces (TrackerDataManager *manager)
return ht;
}
+
+gboolean
+tracker_data_manager_create_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ gint id;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+ if (!tracker_db_manager_attach_database (manager->db_manager, iface,
+ name, TRUE, error))
+ return FALSE;
+
+ if (!tracker_data_ontology_setup_db (manager, iface, name,
+ FALSE, error))
+ goto error;
+
+ id = tracker_data_ensure_graph (manager->data_update, name, error);
+ if (id == 0)
+ goto error;
+
+ g_hash_table_insert (manager->graphs, g_strdup (name), GINT_TO_POINTER (id));
+ return TRUE;
+
+error:
+ tracker_db_manager_detach_database (manager->db_manager, iface, name, NULL);
+ return FALSE;
+}
+
+gboolean
+tracker_data_manager_drop_graph (TrackerDataManager *manager,
+ const gchar *name,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+
+ iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
+
+ if (!tracker_db_manager_detach_database (manager->db_manager, iface,
+ name, error))
+ return FALSE;
+
+ if (!tracker_data_delete_graph (manager->data_update, name, error))
+ return FALSE;
+
+ g_hash_table_remove (manager->graphs, name);
+ return TRUE;
+}
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index 25baa6df7..5c97652e8 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -734,8 +734,6 @@ ensure_graph_id (TrackerData *data,
const gchar *uri,
gboolean *create)
{
- TrackerDBInterface *iface;
- TrackerDBStatement *stmt;
GError *error = NULL;
gint id;
@@ -743,17 +741,7 @@ ensure_graph_id (TrackerData *data,
if (id != 0)
return id;
- id = ensure_resource_id (data, uri, create);
- iface = tracker_data_manager_get_writable_db_interface (data->manager);
- stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, &error,
- "INSERT OR IGNORE INTO Graph (ID) VALUES (?)");
-
- if (stmt) {
- tracker_db_statement_bind_int (stmt, 0, id);
- tracker_db_statement_execute (stmt, &error);
- g_object_unref (stmt);
- }
-
+ id = tracker_data_ensure_graph (data, uri, &error);
if (error) {
g_critical ("Could not ensure graph existence: %s", error->message);
g_error_free (error);
@@ -3412,3 +3400,49 @@ tracker_data_load_turtle_file (TrackerData *data,
tracker_turtle_reader_load (file, data, error);
}
+
+gint
+tracker_data_ensure_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ TrackerDBStatement *stmt;
+ gint id;
+
+ id = ensure_resource_id (data, uri, NULL);
+ iface = tracker_data_manager_get_writable_db_interface (data->manager);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, error,
+ "INSERT OR IGNORE INTO Graph (ID) VALUES (?)");
+ if (!stmt)
+ return 0;
+
+ tracker_db_statement_bind_int (stmt, 0, id);
+ tracker_db_statement_execute (stmt, error);
+ g_object_unref (stmt);
+
+ return id;
+}
+
+gboolean
+tracker_data_delete_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error)
+{
+ TrackerDBInterface *iface;
+ TrackerDBStatement *stmt;
+ gint id;
+
+ id = query_resource_id (data, uri);
+ iface = tracker_data_manager_get_writable_db_interface (data->manager);
+ stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_UPDATE, error,
+ "DELETE FROM Graph WHERE ID = ?");
+ if (!stmt)
+ return FALSE;
+
+ tracker_db_statement_bind_int (stmt, 0, id);
+ tracker_db_statement_execute (stmt, error);
+ g_object_unref (stmt);
+
+ return TRUE;
+}
diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h
index 3acb11f27..5241167fb 100644
--- a/src/libtracker-data/tracker-data-update.h
+++ b/src/libtracker-data/tracker-data-update.h
@@ -118,6 +118,13 @@ void tracker_data_load_turtle_file (TrackerData *
void tracker_data_sync (TrackerData *data);
+gint tracker_data_ensure_graph (TrackerData *data,
+ const gchar *name,
+ GError **error);
+gboolean tracker_data_delete_graph (TrackerData *data,
+ const gchar *uri,
+ GError **error);
+
/* Calling back */
void tracker_data_add_insert_statement_callback (TrackerData *data,
TrackerStatementCallback callback,
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c
b/src/libtracker-data/tracker-db-interface-sqlite.c
index d253df52d..52eca4a9f 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -2382,7 +2382,7 @@ tracker_db_interface_create_statement (TrackerDBInterface *db_interfac
return g_object_ref_sink (stmt);
}
-static void
+static gboolean
execute_stmt (TrackerDBInterface *interface,
sqlite3_stmt *stmt,
GCancellable *cancellable,
@@ -2431,7 +2431,7 @@ execute_stmt (TrackerDBInterface *interface,
g_critical ("SQLite error: %s (errno: %s)",
sqlite3_errmsg (interface->db),
g_strerror (errno));
- return;
+ return FALSE;
}
if (!error) {
@@ -2456,6 +2456,8 @@ execute_stmt (TrackerDBInterface *interface,
}
}
}
+
+ return result == SQLITE_DONE;
}
void
@@ -3171,3 +3173,46 @@ tracker_db_interface_init_vtabs (TrackerDBInterface *db_interface,
tracker_vtab_triples_init (db_interface->db, ontologies);
return TRUE;
}
+
+gboolean
+tracker_db_interface_attach_database (TrackerDBInterface *db_interface,
+ GFile *file,
+ const gchar *name,
+ GError **error)
+{
+ gchar *sql, *path;
+ sqlite3_stmt *stmt;
+ gboolean retval;
+
+ path = g_file_get_path (file);
+ sql = g_strdup_printf ("ATTACH DATABASE \"%s\" AS \"%s\"", path, name);
+ g_free (path);
+
+ stmt = tracker_db_interface_prepare_stmt (db_interface, sql, error);
+ if (!stmt)
+ return FALSE;
+
+ retval = execute_stmt (db_interface, stmt, NULL, error);
+ sqlite3_finalize (stmt);
+ return retval;
+}
+
+gboolean
+tracker_db_interface_detach_database (TrackerDBInterface *db_interface,
+ const gchar *name,
+ GError **error)
+{
+ sqlite3_stmt *stmt;
+ gboolean retval;
+ gchar *sql;
+
+ sql = g_strdup_printf ("DETACH DATABASE \"%s\"", name);
+
+ stmt = tracker_db_interface_prepare_stmt (db_interface, sql, error);
+ if (!stmt)
+ return FALSE;
+
+ retval = execute_stmt (db_interface, stmt, NULL, error);
+ sqlite3_finalize (stmt);
+ return retval;
+}
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.h
b/src/libtracker-data/tracker-db-interface-sqlite.h
index 4608bac94..1715d30ef 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.h
+++ b/src/libtracker-data/tracker-db-interface-sqlite.h
@@ -83,6 +83,14 @@ void tracker_db_interface_sqlite_fts_update_rollback (TrackerD
void tracker_db_interface_sqlite_fts_rebuild_tokens (TrackerDBInterface *interface);
+gboolean tracker_db_interface_attach_database (TrackerDBInterface
*db_interface,
+ GFile *file,
+ const gchar *name,
+ GError **error);
+gboolean tracker_db_interface_detach_database (TrackerDBInterface
*db_interface,
+ const gchar *name,
+ GError **error);
+
#endif
G_END_DECLS
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 09cbf4ded..cb419427d 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -1245,3 +1245,41 @@ tracker_db_manager_check_perform_vacuum (TrackerDBManager *db_manager)
iface = tracker_db_manager_get_writable_db_interface (db_manager);
tracker_db_interface_execute_query (iface, NULL, "VACUUM");
}
+
+gboolean
+tracker_db_manager_attach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ gboolean create,
+ GError **error)
+{
+ gchar *filename;
+ GFile *file;
+
+ filename = g_strdup_printf ("%s.db", name);
+ file = g_file_get_child (db_manager->cache_location, filename);
+ g_free (filename);
+
+ 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_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ }
+ }
+
+ return tracker_db_interface_attach_database (iface, file, name, error);
+}
+
+gboolean
+tracker_db_manager_detach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ GError **error)
+{
+ return tracker_db_interface_detach_database (iface, name, error);
+}
diff --git a/src/libtracker-data/tracker-db-manager.h b/src/libtracker-data/tracker-db-manager.h
index 432a39810..cd95b2529 100644
--- a/src/libtracker-data/tracker-db-manager.h
+++ b/src/libtracker-data/tracker-db-manager.h
@@ -96,6 +96,16 @@ void tracker_db_manager_tokenizer_update (TrackerDBManager
void tracker_db_manager_check_perform_vacuum (TrackerDBManager *db_manager);
+gboolean tracker_db_manager_attach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ gboolean create,
+ GError **error);
+gboolean tracker_db_manager_detach_database (TrackerDBManager *db_manager,
+ TrackerDBInterface *iface,
+ const gchar *name,
+ GError **error);
+
G_END_DECLS
#endif /* __LIBTRACKER_DB_MANAGER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]