summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2020-03-11 01:08:40 +0100
committerSam Thursfield <sam@afuera.me.uk>2020-04-04 15:43:13 +0200
commita0efd1972b122d0a2a867946a068429af5e5228e (patch)
tree141f6e0533a1243b0c4ffdde56b47c4f95605163
parentbbd72ad615ef3f5c1b603f350ce66bca78adbd22 (diff)
downloadtracker-a0efd1972b122d0a2a867946a068429af5e5228e.tar.gz
Allow 'open with existing ontology', disable automatic re-indexing
When the CLI tools open an existing database, the user shouldn't need to specify which ontology to use as the database was already configured with an ontology. These tools can now pass %NULL to the @ontology argument of tracker_sparql_connection_new() to mean "use the existing ontologies". Previously %NULL meant "use the Nepomuk" ontologies. This is now achieved by passing the result of tracker_sparql_get_ontology_nepomuk() for the @ontology parameter. As part of this, I removed the "automatic reindexing" feature of libtracker-data. This feature would delete the database if it detected corruption or a version mismatch, however, that only makes sense for tracker-miner-fs where the data can be recreated from the filesystem. For other usecases this feature is dangerous and should not be happening implicitly -- we now just raise an error in cases of corruption or version mismatches. Closes https://gitlab.gnome.org/GNOME/tracker/issues/192
-rw-r--r--docs/reference/libtracker-sparql/libtracker-sparql-docs.xml1
-rw-r--r--docs/reference/libtracker-sparql/libtracker-sparql-sections.txt1
-rw-r--r--examples/libtracker-sparql/async-connection.c5
-rw-r--r--src/libtracker-data/tracker-data-manager.c119
-rw-r--r--src/libtracker-data/tracker-data-manager.h2
-rw-r--r--src/libtracker-data/tracker-db-manager.c352
-rw-r--r--src/libtracker-data/tracker-db-manager.h23
-rw-r--r--src/libtracker-direct/tracker-direct.c19
-rw-r--r--src/libtracker-sparql-backend/tracker-backend.vala2
-rw-r--r--src/libtracker-sparql/meson.build1
-rw-r--r--src/libtracker-sparql/tracker-connection.c28
-rw-r--r--src/libtracker-sparql/tracker-utils.c13
-rw-r--r--src/libtracker-sparql/tracker-utils.h5
-rw-r--r--src/tracker/tracker-sql.c2
-rw-r--r--tests/libtracker-data/tracker-insert-or-replace-test.c2
-rw-r--r--tests/libtracker-data/tracker-ontology-change-test.c5
-rw-r--r--tests/libtracker-data/tracker-ontology-test.c10
-rw-r--r--tests/libtracker-data/tracker-sparql-blank-test.c4
-rw-r--r--tests/libtracker-data/tracker-sparql-test.c5
-rw-r--r--tests/libtracker-fts/tracker-fts-test.c4
20 files changed, 242 insertions, 361 deletions
diff --git a/docs/reference/libtracker-sparql/libtracker-sparql-docs.xml b/docs/reference/libtracker-sparql/libtracker-sparql-docs.xml
index 12a9c16ce..7e00c13bf 100644
--- a/docs/reference/libtracker-sparql/libtracker-sparql-docs.xml
+++ b/docs/reference/libtracker-sparql/libtracker-sparql-docs.xml
@@ -36,6 +36,7 @@
<xi:include href="xml/tracker-sparql-cursor.xml"/>
<xi:include href="xml/tracker-notifier.xml"/>
<xi:include href="xml/tracker-endpoint.xml"/>
+ <xi:include href="xml/tracker-ontologies.xml"/>
<xi:include href="xml/tracker-misc.xml"/>
<xi:include href="xml/tracker-version.xml"/>
</part>
diff --git a/docs/reference/libtracker-sparql/libtracker-sparql-sections.txt b/docs/reference/libtracker-sparql/libtracker-sparql-sections.txt
index 0856947f6..c12976073 100644
--- a/docs/reference/libtracker-sparql/libtracker-sparql-sections.txt
+++ b/docs/reference/libtracker-sparql/libtracker-sparql-sections.txt
@@ -7,6 +7,7 @@ tracker_sparql_escape_string
tracker_sparql_escape_uri
tracker_sparql_escape_uri_printf
tracker_sparql_escape_uri_vprintf
+tracker_sparql_get_ontology_nepomuk
<SUBSECTION Standard>
TRACKER_TYPE_URI
tracker_uri_get_type
diff --git a/examples/libtracker-sparql/async-connection.c b/examples/libtracker-sparql/async-connection.c
index 6d44cf607..40ae55a34 100644
--- a/examples/libtracker-sparql/async-connection.c
+++ b/examples/libtracker-sparql/async-connection.c
@@ -137,7 +137,7 @@ connection_cb (GObject *object,
gint
main (gint argc, gchar *argv[])
{
- GFile *store;
+ g_autoptr(GFile) store, ontology;
MyData *md;
if (argc > 1) {
@@ -152,9 +152,10 @@ main (gint argc, gchar *argv[])
md->timer = g_timer_new ();
md->cancellable = g_cancellable_new ();
+ ontology = tracker_sparql_get_ontology_nepomuk ();
tracker_sparql_connection_new_async (0,
store,
- NULL,
+ ontology,
md->cancellable,
connection_cb,
md);
diff --git a/src/libtracker-data/tracker-data-manager.c b/src/libtracker-data/tracker-data-manager.c
index 3bf8223f3..6aa496118 100644
--- a/src/libtracker-data/tracker-data-manager.c
+++ b/src/libtracker-data/tracker-data-manager.c
@@ -69,8 +69,6 @@ struct _TrackerDataManager {
GFile *ontology_location;
GFile *cache_location;
guint initialized : 1;
- guint restoring_backup : 1;
- guint first_time_index : 1;
guint flags;
gint select_cache_size;
@@ -3853,7 +3851,6 @@ TrackerDataManager *
tracker_data_manager_new (TrackerDBManagerFlags flags,
GFile *cache_location,
GFile *ontology_location,
- gboolean restoring_backup,
guint select_cache_size,
guint update_cache_size)
{
@@ -3864,18 +3861,12 @@ tracker_data_manager_new (TrackerDBManagerFlags flags,
return NULL;
}
- if ((flags & TRACKER_DB_MANAGER_READONLY) == 0 && !ontology_location) {
- g_warning ("Ontology location must be provided");
- return NULL;
- }
-
manager = g_object_new (TRACKER_TYPE_DATA_MANAGER, NULL);
/* TODO: Make these properties */
g_set_object (&manager->cache_location, cache_location);
g_set_object (&manager->ontology_location, ontology_location);
manager->flags = flags;
- manager->restoring_backup = restoring_backup;
manager->select_cache_size = select_cache_size;
manager->update_cache_size = update_cache_size;
@@ -4064,7 +4055,7 @@ tracker_data_manager_initable_init (GInitable *initable,
{
TrackerDataManager *manager = TRACKER_DATA_MANAGER (initable);
TrackerDBInterface *iface;
- gboolean is_first_time_index, check_ontology, has_graph_table = FALSE;
+ gboolean is_create, has_graph_table = FALSE;
TrackerDBCursor *cursor;
TrackerDBStatement *stmt;
GHashTable *ontos_table;
@@ -4094,14 +4085,13 @@ tracker_data_manager_initable_init (GInitable *initable,
manager->db_manager = tracker_db_manager_new (manager->flags,
manager->cache_location,
- &is_first_time_index,
- manager->restoring_backup,
+ &is_create,
FALSE,
manager->select_cache_size,
manager->update_cache_size,
- busy_callback, manager, "",
+ busy_callback, manager,
G_OBJECT (manager),
- manager->ontologies,
+ manager->ontologies,
&internal_error);
if (!manager->db_manager) {
g_propagate_error (error, internal_error);
@@ -4113,8 +4103,6 @@ tracker_data_manager_initable_init (GInitable *initable,
g_signal_connect (manager->db_manager, "update-interface",
G_CALLBACK (update_interface_cb), manager);
- manager->first_time_index = is_first_time_index;
-
tracker_data_manager_update_status (manager, "Initializing data manager");
iface = tracker_db_manager_get_writable_db_interface (manager->db_manager);
@@ -4131,7 +4119,11 @@ tracker_data_manager_initable_init (GInitable *initable,
return FALSE;
}
- if (is_first_time_index && !read_only) {
+ if (is_create) {
+ TrackerOntology **ontologies;
+ guint n_ontologies, i;
+
+ g_info ("Applying ontologies from %s", g_file_peek_path (manager->ontology_location));
sorted = get_ontologies (manager, manager->ontology_location, &internal_error);
if (internal_error) {
@@ -4139,8 +4131,6 @@ tracker_data_manager_initable_init (GInitable *initable,
return FALSE;
}
- /* load ontology from files into memory (max_id starts at zero: first-time) */
-
for (l = sorted; l; l = l->next) {
GError *ontology_error = NULL;
GFile *ontology_file = l->data;
@@ -4177,7 +4167,7 @@ tracker_data_manager_initable_init (GInitable *initable,
if (!internal_error) {
tracker_data_ontology_import_into_db (manager, iface,
- FALSE,
+ FALSE,
&internal_error);
}
@@ -4208,59 +4198,61 @@ tracker_data_manager_initable_init (GInitable *initable,
write_ontologies_gvdb (manager, TRUE /* overwrite */, NULL);
- g_list_free_full (sorted, g_object_unref);
- sorted = NULL;
+ ontologies = tracker_ontologies_get_ontologies (manager->ontologies, &n_ontologies);
- /* First time, no need to check ontology */
- check_ontology = FALSE;
- } else {
- if (!read_only) {
- /* Load ontology from database into memory */
- db_get_static_data (iface, manager, &internal_error);
- check_ontology = (manager->flags & TRACKER_DB_MANAGER_DO_NOT_CHECK_ONTOLOGY) == 0;
+ for (i = 0; i < n_ontologies; i++) {
+ GError *n_error = NULL;
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return FALSE;
+ update_ontology_last_modified (manager, iface, ontologies[i], &n_error);
+
+ if (n_error) {
+ g_critical ("%s", n_error->message);
+ g_clear_error (&n_error);
}
+ }
- write_ontologies_gvdb (manager, FALSE /* overwrite */, NULL);
- } else {
- GError *gvdb_error = NULL;
+ g_list_free_full (sorted, g_object_unref);
+ sorted = NULL;
+ } else {
+ GError *gvdb_error = NULL;
+ gboolean load_from_db = TRUE;
+ if (read_only) {
+ /* Not all ontology information is saved in the gvdb cache, so
+ * it can only be used for read-only connections. */
+ g_info ("Loading cached ontologies from gvdb cache");
load_ontologies_gvdb (manager, &gvdb_error);
- check_ontology = FALSE;
if (gvdb_error) {
+ g_debug ("Error loading ontology cache: %s. ", gvdb_error->message);
g_clear_error (&gvdb_error);
-
- /* fall back to loading ontology from database into memory */
- db_get_static_data (iface, manager, &internal_error);
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return FALSE;
- }
+ } else {
+ load_from_db = FALSE;
}
}
- tracker_data_manager_initialize_iface (manager, iface, &internal_error);
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return FALSE;
+ if (load_from_db) {
+ g_info ("Loading ontologies from database.");
+
+ db_get_static_data (iface, manager, &internal_error);
+ if (internal_error) {
+ g_propagate_error (error, internal_error);
+ return FALSE;
+ }
+
+ if (!read_only) {
+ write_ontologies_gvdb (manager, FALSE /* overwrite */, NULL);
+ }
}
- }
- if (!read_only) {
- has_graph_table = query_table_exists (iface, "Graph", &internal_error);
+ tracker_data_manager_initialize_iface (manager, iface, &internal_error);
if (internal_error) {
g_propagate_error (error, internal_error);
return FALSE;
}
-
- check_ontology |= !has_graph_table;
}
- if (check_ontology) {
+ if (!is_create && manager->ontology_location) {
GList *to_reload = NULL;
GList *ontos = NULL;
GPtrArray *seen_classes;
@@ -4271,6 +4263,8 @@ tracker_data_manager_initable_init (GInitable *initable,
seen_classes = g_ptr_array_new ();
seen_properties = g_ptr_array_new ();
+ g_info ("Applying ontologies from %s to existing database", g_file_peek_path (manager->ontology_location));
+
/* Get all the ontology files from ontology_location */
ontos = get_ontologies (manager, manager->ontology_location, &internal_error);
@@ -4355,6 +4349,7 @@ tracker_data_manager_initable_init (GInitable *initable,
GError *ontology_error = NULL;
gint val = GPOINTER_TO_INT (value);
+ has_graph_table = query_table_exists (iface, "Graph", &internal_error);
if (!has_graph_table) {
/* No graph table and no resource triggers,
* the table must be recreated.
@@ -4632,26 +4627,12 @@ tracker_data_manager_initable_init (GInitable *initable,
g_hash_table_unref (ontos_table);
g_list_free_full (ontos, g_object_unref);
- } else if (is_first_time_index && !read_only) {
- TrackerOntology **ontologies;
- guint n_ontologies, i;
-
- ontologies = tracker_ontologies_get_ontologies (manager->ontologies, &n_ontologies);
-
- for (i = 0; i < n_ontologies; i++) {
- GError *n_error = NULL;
- update_ontology_last_modified (manager, iface, ontologies[i], &n_error);
-
- if (n_error) {
- g_critical ("%s", n_error->message);
- g_clear_error (&n_error);
- }
- }
}
+
skip_ontology_check:
- if (!read_only && is_first_time_index) {
+ if (!read_only && is_create) {
tracker_db_manager_set_current_locale (manager->db_manager);
tracker_db_manager_tokenizer_update (manager->db_manager);
} else if (!read_only && tracker_db_manager_locale_changed (manager->db_manager, NULL)) {
diff --git a/src/libtracker-data/tracker-data-manager.h b/src/libtracker-data/tracker-data-manager.h
index c3dd32d6d..af558789c 100644
--- a/src/libtracker-data/tracker-data-manager.h
+++ b/src/libtracker-data/tracker-data-manager.h
@@ -59,10 +59,10 @@ typedef enum {
GType tracker_data_manager_get_type (void) G_GNUC_CONST;
GQuark tracker_data_ontology_error_quark (void);
+
TrackerDataManager * tracker_data_manager_new (TrackerDBManagerFlags flags,
GFile *cache_location,
GFile *ontology_location,
- gboolean restoring_backup,
guint select_cache_size,
guint update_cache_size);
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 8292673aa..cca9350d7 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -240,28 +240,6 @@ db_set_params (TrackerDBInterface *iface,
g_debug (" Setting cache size to %d", cache_size);
}
-static void
-tracker_db_manager_remove_all (TrackerDBManager *db_manager)
-{
- gchar *filename;
-
- if ((db_manager->flags & TRACKER_DB_MANAGER_IN_MEMORY) != 0)
- return;
-
- g_info ("Removing all files for database %s", db_manager->db.abs_filename);
-
- g_unlink (db_manager->db.abs_filename);
-
- /* also delete shm and wal helper files */
- filename = g_strdup_printf ("%s-shm", db_manager->db.abs_filename);
- g_unlink (filename);
- g_free (filename);
-
- filename = g_strdup_printf ("%s-wal", db_manager->db.abs_filename);
- g_unlink (filename);
- g_free (filename);
-}
-
static gboolean
tracker_db_manager_get_metadata (TrackerDBManager *db_manager,
const gchar *key,
@@ -447,33 +425,6 @@ tracker_db_manager_set_current_locale (TrackerDBManager *db_manager)
}
static void
-db_recreate_all (TrackerDBManager *db_manager,
- GError **error)
-{
- GError *internal_error = NULL;
-
- /* We call an internal version of this function here
- * because at the time 'initialized' = FALSE and that
- * will cause errors and do nothing.
- */
- g_debug ("Cleaning up database files for reindex");
-
- tracker_db_manager_remove_all (db_manager);
-
- /* Now create the databases and close them */
- g_info ("Creating database files for %s...", db_manager->db.abs_filename);
-
- db_manager->db.iface = tracker_db_manager_create_db_interface (db_manager, FALSE, &internal_error);
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return;
- }
-
- g_clear_object (&db_manager->db.iface);
- g_clear_object (&db_manager->db.wal_iface);
-}
-
-static void
tracker_db_manager_ensure_location (TrackerDBManager *db_manager,
GFile *cache_location)
{
@@ -497,57 +448,98 @@ tracker_db_manager_ensure_location (TrackerDBManager *db_manager,
g_free (dir);
}
-static void
-perform_recreate (TrackerDBManager *db_manager,
- gboolean *first_time,
- GError **error)
+gboolean
+tracker_db_manager_db_exists (GFile *cache_location)
+{
+ gchar *dir;
+ gchar *filename;
+ gboolean db_exists = FALSE;
+
+ dir = g_file_get_path (cache_location);
+ filename = g_build_filename (dir, db_base.file, NULL);
+
+ db_exists = g_file_test (filename, G_FILE_TEST_EXISTS);
+
+ g_free (dir);
+ g_free (filename);
+
+ return db_exists;
+}
+
+static gboolean
+db_check_integrity (TrackerDBManager *db_manager)
{
GError *internal_error = NULL;
+ TrackerDBStatement *stmt;
+ TrackerDBCursor *cursor = NULL;
- if (first_time) {
- *first_time = TRUE;
+ stmt = tracker_db_interface_create_statement (db_manager->db.iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
+ &internal_error,
+ "PRAGMA integrity_check(1)");
+
+ if (!stmt) {
+ if (internal_error) {
+ g_message ("Corrupt database: failed to create integrity_check statement: %s", internal_error->message);
+ }
+
+ g_clear_error (&internal_error);
+ return FALSE;
}
- g_clear_object (&db_manager->db.iface);
- g_clear_object (&db_manager->db.wal_iface);
+ cursor = tracker_db_statement_start_cursor (stmt, NULL);
+ g_object_unref (stmt);
- if ((db_manager->flags & TRACKER_DB_MANAGER_IN_MEMORY) == 0 &&
- !tracker_file_system_has_enough_space (db_manager->data_dir, TRACKER_DB_MIN_REQUIRED_SPACE, TRUE)) {
- g_set_error (error,
- TRACKER_DB_INTERFACE_ERROR,
- TRACKER_DB_OPEN_ERROR,
- "Filesystem has not enough space");
- return;
+ if (cursor) {
+ if (tracker_db_cursor_iter_next (cursor, NULL, NULL)) {
+ const gchar *check_result;
+
+ check_result = tracker_db_cursor_get_string (cursor, 0, NULL);
+ if (g_strcmp0 (check_result, "ok") != 0) {
+ g_message ("Corrupt database: sqlite integrity check returned '%s'", check_result);
+ return FALSE;
+ }
+ }
+ g_object_unref (cursor);
}
- db_recreate_all (db_manager, &internal_error);
+ /* ensure that database has been initialized by an earlier tracker-store start
+ by checking whether Resource table exists */
+ stmt = tracker_db_interface_create_statement (db_manager->db.iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
+ &internal_error,
+ "SELECT 1 FROM Resource");
+ if (!stmt) {
+ if (internal_error) {
+ g_message ("Corrupt database: failed to create resource check statement: %s", internal_error->message);
+ }
- if (internal_error) {
- g_propagate_error (error, internal_error);
+ g_clear_error (&internal_error);
+ return FALSE;
}
+
+ g_object_unref (stmt);
+
+ return TRUE;
}
TrackerDBManager *
tracker_db_manager_new (TrackerDBManagerFlags flags,
GFile *cache_location,
gboolean *first_time,
- gboolean restoring_backup,
gboolean shared_cache,
guint select_cache_size,
guint update_cache_size,
TrackerBusyCallback busy_callback,
gpointer busy_user_data,
- const gchar *busy_operation,
GObject *iface_data,
gpointer vtab_data,
GError **error)
{
TrackerDBManager *db_manager;
TrackerDBVersion version;
- gboolean need_reindex;
int in_use_file;
TrackerDBInterface *resources_iface;
GError *internal_error = NULL;
+ gboolean need_to_create = FALSE;
db_manager = g_object_new (TRACKER_TYPE_DB_MANAGER, NULL);
db_manager->vtab_data = vtab_data;
@@ -557,8 +549,6 @@ tracker_db_manager_new (TrackerDBManagerFlags flags,
*first_time = FALSE;
}
- need_reindex = FALSE;
-
/* Set up locations */
g_debug ("Setting database locations");
@@ -590,18 +580,12 @@ tracker_db_manager_new (TrackerDBManagerFlags flags,
g_debug ("Checking whether database files exist");
- /* Check we have the database in place, if it is
- * missing, we reindex.
- *
- * There's no need to check for files not existing (for
- * reindex) if reindexing is already needed.
- */
if ((db_manager->flags & TRACKER_DB_MANAGER_IN_MEMORY) != 0) {
- need_reindex = TRUE;
+ need_to_create = TRUE;
} else if (!g_file_test (db_manager->db.abs_filename, G_FILE_TEST_EXISTS)) {
if ((flags & TRACKER_DB_MANAGER_READONLY) == 0) {
- g_info ("Could not find database file:'%s', reindex will be forced", db_manager->db.abs_filename);
- need_reindex = TRUE;
+ g_info ("Could not find database file:'%s', will create it.", db_manager->db.abs_filename);
+ need_to_create = TRUE;
} else {
g_set_error (error,
TRACKER_DB_INTERFACE_ERROR,
@@ -612,29 +596,25 @@ tracker_db_manager_new (TrackerDBManagerFlags flags,
return NULL;
}
} else {
- g_info ("Checking database version");
+ g_debug ("Checking database version");
version = db_get_version (db_manager);
if (version < TRACKER_DB_VERSION_NOW) {
- g_info (" A reindex will be forced");
- need_reindex = TRUE;
+ g_set_error (error,
+ TRACKER_DB_INTERFACE_ERROR,
+ TRACKER_DB_OPEN_ERROR,
+ "Database version is too old: got version %i, but %i is needed",
+ version, TRACKER_DB_VERSION_NOW);
+
+ g_object_unref (db_manager);
+ return NULL;
}
}
-
db_manager->locations_initialized = TRUE;
- /* Don't do remove-dbs for readonly (direct-access) */
- if ((flags & TRACKER_DB_MANAGER_READONLY) == 0) {
-
- /* If we are just initializing to remove the databases,
- * return here.
- */
- if ((flags & TRACKER_DB_MANAGER_REMOVE_ALL) != 0) {
- return db_manager;
- }
- } else {
+ if ((flags & TRACKER_DB_MANAGER_READONLY) != 0) {
GValue value = G_VALUE_INIT;
TrackerDBManagerFlags fts_flags = 0;
@@ -655,160 +635,76 @@ tracker_db_manager_new (TrackerDBManagerFlags flags,
tracker_db_interface_sqlite_enable_shared_cache ();
}
- /* Should we reindex? If so, just remove all databases files,
- * NOT the paths, note, that these paths are also used for
- * other things like the nfs lock file.
- */
- if (flags & TRACKER_DB_MANAGER_FORCE_REINDEX || need_reindex) {
-
- if (flags & TRACKER_DB_MANAGER_READONLY) {
- /* no reindexing supported in read-only mode (direct access) */
+ if (need_to_create) {
+ *first_time = TRUE;
+ if ((db_manager->flags & TRACKER_DB_MANAGER_IN_MEMORY) == 0 &&
+ !tracker_file_system_has_enough_space (db_manager->data_dir, TRACKER_DB_MIN_REQUIRED_SPACE, TRUE)) {
g_set_error (error,
TRACKER_DB_INTERFACE_ERROR,
TRACKER_DB_OPEN_ERROR,
- "No reindexing supported in read-only mode (direct access)");
-
- g_object_unref (db_manager);
- return NULL;
+ "Filesystem does not have enough space");
+ return FALSE;
}
- perform_recreate (db_manager, first_time, &internal_error);
+ g_info ("Creating database files for %s...", db_manager->db.abs_filename);
+ db_manager->db.iface = tracker_db_manager_create_db_interface (db_manager, FALSE, &internal_error);
if (internal_error) {
g_propagate_error (error, internal_error);
g_object_unref (db_manager);
- return NULL;
+ return FALSE;
}
- tracker_db_manager_update_version (db_manager);
- } else if ((flags & TRACKER_DB_MANAGER_READONLY) == 0) {
- /* do not do shutdown check for read-only mode (direct access) */
- gboolean must_recreate = FALSE;
+ g_clear_object (&db_manager->db.iface);
- /* Load databases */
+ tracker_db_manager_update_version (db_manager);
+ } else {
g_info ("Loading files for database %s...", db_manager->db.abs_filename);
- if (!must_recreate && g_file_test (db_manager->in_use_filename, G_FILE_TEST_EXISTS)) {
- gsize size = 0;
- struct stat st;
- TrackerDBStatement *stmt;
+ if ((flags & TRACKER_DB_MANAGER_READONLY) == 0) {
+ /* Check that the database was closed cleanly and do a deeper integrity
+ * check if it wasn't, raising an error if we detect corruption. */
- g_info ("Didn't shut down cleanly last time, doing integrity checks");
+ if (g_file_test (db_manager->in_use_filename, G_FILE_TEST_EXISTS)) {
+ gsize size = 0;
+ struct stat st;
- if (g_stat (db_manager->db.abs_filename, &st) == 0) {
- size = st.st_size;
- }
+ g_info ("Didn't shut down cleanly last time, doing integrity checks");
- /* Size is 1 when using echo > file.db, none of our databases
- * are only one byte in size even initually. */
+ if (g_stat (db_manager->db.abs_filename, &st) == 0) {
+ size = st.st_size;
+ }
- if (size <= 1) {
- if (!restoring_backup) {
- must_recreate = TRUE;
- } else {
- g_set_error (error,
- TRACKER_DB_INTERFACE_ERROR,
- TRACKER_DB_OPEN_ERROR,
- "Corrupt db file");
- g_object_unref (db_manager);
- return NULL;
+ /* Size is 1 when using echo > file.db, none of our databases
+ * are only one byte in size even initually. */
+ if (size <= 1) {
+ g_info ("Database is corrupt: size is 1 byte or less.");
+ return FALSE;
}
- }
- if (!must_recreate) {
db_manager->db.iface = tracker_db_manager_create_db_interface (db_manager, FALSE, &internal_error);
if (internal_error) {
/* If this already doesn't succeed, then surely the file is
* corrupt. No need to check for integrity anymore. */
- if (!restoring_backup) {
- g_clear_error (&internal_error);
- must_recreate = TRUE;
- } else {
- g_propagate_error (error, internal_error);
- g_object_unref (db_manager);
- return NULL;
- }
+ g_propagate_error (error, internal_error);
+ g_object_unref (db_manager);
+ return NULL;
}
- }
- if (!must_recreate) {
- gchar *busy_status;
-
- /* Report OPERATION - STATUS */
- busy_status = g_strdup_printf ("%s - %s",
- busy_operation,
- "Integrity checking");
- busy_callback (busy_status, 0, busy_user_data);
- g_free (busy_status);
-
- stmt = tracker_db_interface_create_statement (db_manager->db.iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
- &internal_error,
- "PRAGMA integrity_check(1)");
-
- if (internal_error != NULL) {
- if (internal_error->domain == TRACKER_DB_INTERFACE_ERROR &&
- internal_error->code == TRACKER_DB_QUERY_ERROR) {
- must_recreate = TRUE;
- } else {
- g_critical ("%s", internal_error->message);
- }
- g_error_free (internal_error);
- internal_error = NULL;
- } else {
- TrackerDBCursor *cursor = NULL;
-
- if (stmt) {
- cursor = tracker_db_statement_start_cursor (stmt, NULL);
- g_object_unref (stmt);
- } else {
- g_critical ("Can't create stmt for integrity_check, no error given");
- }
-
- if (cursor) {
- if (tracker_db_cursor_iter_next (cursor, NULL, NULL)) {
- if (g_strcmp0 (tracker_db_cursor_get_string (cursor, 0, NULL), "ok") != 0) {
- must_recreate = TRUE;
- }
- }
- g_object_unref (cursor);
- }
- }
- }
+ busy_callback ("Integrity checking", 0, busy_user_data);
- if (!must_recreate) {
- /* ensure that database has been initialized by an earlier tracker-store start
- by checking whether Resource table exists */
- stmt = tracker_db_interface_create_statement (db_manager->db.iface, TRACKER_DB_STATEMENT_CACHE_TYPE_NONE,
- &internal_error,
- "SELECT 1 FROM Resource");
- if (internal_error != NULL) {
- if (!restoring_backup) {
- must_recreate = TRUE;
- g_error_free (internal_error);
- internal_error = NULL;
- }
- } else {
- g_object_unref (stmt);
+ if (db_check_integrity (db_manager) == FALSE) {
+ g_set_error (error,
+ TRACKER_DB_INTERFACE_ERROR,
+ TRACKER_DB_OPEN_ERROR,
+ "Corrupt db file");
+ g_object_unref (db_manager);
+ return NULL;
}
}
}
-
- if (must_recreate) {
- g_info ("Database severely damaged. We will recreate it.");
-
- perform_recreate (db_manager, first_time, &internal_error);
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return FALSE;
- }
- } else {
- if (internal_error) {
- g_propagate_error (error, internal_error);
- return FALSE;
- }
- }
}
if ((flags & (TRACKER_DB_MANAGER_READONLY | TRACKER_DB_MANAGER_IN_MEMORY)) == 0) {
@@ -827,25 +723,9 @@ tracker_db_manager_new (TrackerDBManagerFlags flags,
TRUE, &internal_error);
if (internal_error) {
- if ((!restoring_backup) && (flags & TRACKER_DB_MANAGER_READONLY) == 0) {
- GError *new_error = NULL;
-
- perform_recreate (db_manager, first_time, &new_error);
- if (!new_error) {
- resources_iface = tracker_db_manager_create_db_interface (db_manager, TRUE,
- &internal_error);
- } else {
- /* Most serious error is the recreate one here */
- g_clear_error (&internal_error);
- g_propagate_error (error, new_error);
- g_object_unref (db_manager);
- return NULL;
- }
- } else {
- g_propagate_error (error, internal_error);
- g_object_unref (db_manager);
- return NULL;
- }
+ g_propagate_error (error, internal_error);
+ g_object_unref (db_manager);
+ return NULL;
}
g_clear_object (&resources_iface);
diff --git a/src/libtracker-data/tracker-db-manager.h b/src/libtracker-data/tracker-db-manager.h
index 91136dc3a..486e337ba 100644
--- a/src/libtracker-data/tracker-db-manager.h
+++ b/src/libtracker-data/tracker-db-manager.h
@@ -38,30 +38,29 @@ G_DECLARE_FINAL_TYPE (TrackerDBManager, tracker_db_manager,
#define TRACKER_DB_CACHE_SIZE_UPDATE 2000
typedef enum {
- TRACKER_DB_MANAGER_FORCE_REINDEX = 1 << 1,
- TRACKER_DB_MANAGER_REMOVE_ALL = 1 << 2,
- TRACKER_DB_MANAGER_READONLY = 1 << 3,
- TRACKER_DB_MANAGER_DO_NOT_CHECK_ONTOLOGY = 1 << 4,
- TRACKER_DB_MANAGER_ENABLE_MUTEXES = 1 << 5,
- TRACKER_DB_MANAGER_FTS_ENABLE_STEMMER = 1 << 6,
- TRACKER_DB_MANAGER_FTS_ENABLE_UNACCENT = 1 << 7,
- TRACKER_DB_MANAGER_FTS_ENABLE_STOP_WORDS = 1 << 8,
- TRACKER_DB_MANAGER_FTS_IGNORE_NUMBERS = 1 << 9,
- TRACKER_DB_MANAGER_IN_MEMORY = 1 << 10,
+ TRACKER_DB_MANAGER_FLAGS_NONE = 0,
+ TRACKER_DB_MANAGER_READONLY = 1 << 1,
+ TRACKER_DB_MANAGER_DO_NOT_CHECK_ONTOLOGY = 1 << 2,
+ TRACKER_DB_MANAGER_ENABLE_MUTEXES = 1 << 3,
+ TRACKER_DB_MANAGER_FTS_ENABLE_STEMMER = 1 << 4,
+ TRACKER_DB_MANAGER_FTS_ENABLE_UNACCENT = 1 << 5,
+ TRACKER_DB_MANAGER_FTS_ENABLE_STOP_WORDS = 1 << 6,
+ TRACKER_DB_MANAGER_FTS_IGNORE_NUMBERS = 1 << 7,
+ TRACKER_DB_MANAGER_IN_MEMORY = 1 << 8,
} TrackerDBManagerFlags;
typedef struct _TrackerDBManager TrackerDBManager;
+gboolean tracker_db_manager_db_exists (GFile *cache_location);
+
TrackerDBManager *tracker_db_manager_new (TrackerDBManagerFlags flags,
GFile *cache_location,
gboolean *first_time,
- gboolean restoring_backup,
gboolean shared_cache,
guint select_cache_size,
guint update_cache_size,
TrackerBusyCallback busy_callback,
gpointer busy_user_data,
- const gchar *busy_operation,
GObject *iface_data,
gpointer vtab_data,
GError **error);
diff --git a/src/libtracker-direct/tracker-direct.c b/src/libtracker-direct/tracker-direct.c
index c625cee10..1994579ca 100644
--- a/src/libtracker-direct/tracker-direct.c
+++ b/src/libtracker-direct/tracker-direct.c
@@ -257,26 +257,13 @@ tracker_direct_connection_initable_init (GInitable *initable,
db_flags = translate_flags (priv->flags);
- if (!priv->store)
+ if (!priv->store) {
db_flags |= TRACKER_DB_MANAGER_IN_MEMORY;
-
- /* Init data manager */
- if (!priv->ontology &&
- (db_flags & TRACKER_DB_MANAGER_READONLY) == 0) {
- gchar *filename;
-
- /* If the connection is read/write, and no ontology is specified,
- * we use the Nepomuk one.
- */
- filename = g_build_filename (SHAREDIR, "tracker", "ontologies",
- "nepomuk", NULL);
- priv->ontology = g_file_new_for_path (filename);
- g_free (filename);
}
priv->data_manager = tracker_data_manager_new (db_flags, priv->store,
priv->ontology,
- FALSE, 100, 100);
+ 100, 100);
if (!g_initable_init (G_INITABLE (priv->data_manager), cancellable, error)) {
g_clear_object (&priv->data_manager);
return FALSE;
@@ -1034,7 +1021,7 @@ tracker_direct_connection_class_init (TrackerDirectConnectionClass *klass)
TrackerDirectConnection *
tracker_direct_connection_new (TrackerSparqlConnectionFlags flags,
- GFile *store,
+ GFile *store,
GFile *ontology,
GError **error)
{
diff --git a/src/libtracker-sparql-backend/tracker-backend.vala b/src/libtracker-sparql-backend/tracker-backend.vala
index 7e8ee79fb..79db936a1 100644
--- a/src/libtracker-sparql-backend/tracker-backend.vala
+++ b/src/libtracker-sparql-backend/tracker-backend.vala
@@ -44,7 +44,7 @@ public static Tracker.Sparql.Connection tracker_sparql_connection_new (Tracker.S
return conn;
}
-public static async Tracker.Sparql.Connection tracker_sparql_connection_new_async (Tracker.Sparql.ConnectionFlags flags, File store, File? ontology, Cancellable? cancellable = null) throws GLib.Error, Tracker.Sparql.Error, IOError {
+public static async Tracker.Sparql.Connection tracker_sparql_connection_new_async (Tracker.Sparql.ConnectionFlags flags, File store, File ontology, Cancellable? cancellable = null) throws GLib.Error, Tracker.Sparql.Error, IOError {
var conn = new Tracker.Direct.Connection (flags, store, ontology);
conn.init_async.begin (Priority.DEFAULT, cancellable);
yield;
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index 9ddbe51a6..21e22275b 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -30,6 +30,7 @@ libtracker_sparql_c_public_headers = files(
'tracker-endpoint-dbus.h',
'tracker-namespace-manager.h',
'tracker-notifier.h',
+ 'tracker-ontologies.h',
'tracker-resource.h',
'tracker-statement.h',
'tracker-utils.h',
diff --git a/src/libtracker-sparql/tracker-connection.c b/src/libtracker-sparql/tracker-connection.c
index 16c72d723..a528b5dcb 100644
--- a/src/libtracker-sparql/tracker-connection.c
+++ b/src/libtracker-sparql/tracker-connection.c
@@ -54,18 +54,33 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
* tracker_sparql_connection_new:
* @flags: values from #TrackerSparqlConnectionFlags
* @store: the directory that contains the database as a #GFile, or %NULL
- * @ontology: (nullable): the directory that contains the database schemas as
- * a #GFile, or %NULL to use the default schemas.
+ * @ontology: the directory that contains the database schemas as a #GFile, or %NULL
* @cancellable: (nullable): a #GCancellable, or %NULL
* @error: pointer to a #GError
*
- * Opens a database. Use this for data managed by the current process.
+ * Creates or opens a database.
*
+ * This method should only be used for databases owned by the current process.
* To connect to databases managed by other processes, use
* tracker_sparql_connection_bus_new().
*
* If @store is %NULL, the database will be created in memory.
*
+ * The @ontologies parameter must point to a location containing suitable
+ * `.ontology` files in Turtle format. These control the database schema that
+ * is used. You can use the default Nepomuk ontologies by calling
+ * tracker_sparql_get_ontology_nepomuk ().
+ *
+ * If you open an existing database using a different @ontology to the one it
+ * was created with, Tracker will attempt to migrate the existing data to the
+ * new schema. This may raise an error. In particular, not all migrations are
+ * possible without causing data loss and Tracker will refuse to delete data
+ * during a migration.
+ *
+ * You can also pass %NULL for @ontologies to mean "use the ontologies that the
+ * database was created with". This will fail if the database doesn't already
+ * exist.
+ *
* Returns: (transfer full): a new #TrackerSparqlConnection. Call
* g_object_unref() on the object when no longer used.
*
@@ -75,9 +90,8 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
/**
* tracker_sparql_connection_new_async:
* @flags: values from #TrackerSparqlConnectionFlags
- * @store: the directory that contains the database as a #GFile, or %NULL
- * @ontology: (nullable): the directory that contains the database schemas as
- * a #GFile, or %NULL to use the default schemas.
+ * @store: (nullable): the directory that contains the database as a #GFile, or %NULL
+ * @ontology: (nullable): the directory that contains the database schemas as a #GFile, or %NULL
* @cancellable: (nullable): a #GCancellable, or %NULL
* @callback: the #GAsyncReadyCallback called when the operation completes
* @user_data: data passed to @callback
@@ -101,7 +115,7 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
* tracker_sparql_connection_bus_new:
* @service_name: The name of the D-Bus service to connect to.
* @object_path: (nullable): The path to the object, or %NULL to use the default.
- * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus.
+ * @dbus_connection: (nullable): The #GDBusConnection to use, or %NULL to use the session bus
* @error: pointer to a #GError
*
* Connects to a database owned by another process on the
diff --git a/src/libtracker-sparql/tracker-utils.c b/src/libtracker-sparql/tracker-utils.c
index e630b689a..774b7e52c 100644
--- a/src/libtracker-sparql/tracker-utils.c
+++ b/src/libtracker-sparql/tracker-utils.c
@@ -78,3 +78,16 @@ tracker_sparql_get_uuid_urn (void)
{
return tracker_generate_uuid ("urn:uuid");
}
+
+/**
+ * tracker_sparql_get_ontology_nepomuk:
+ *
+ * Returns a path to the built-in Nepomuk ontologies.
+ *
+ * Returns: (transfer full): a #GFile instance.
+ */
+GFile *
+tracker_sparql_get_ontology_nepomuk (void)
+{
+ return g_file_new_for_path (SHAREDIR "/tracker/ontologies/nepomuk");
+}
diff --git a/src/libtracker-sparql/tracker-utils.h b/src/libtracker-sparql/tracker-utils.h
index 6acfcaecf..36c7d1c8f 100644
--- a/src/libtracker-sparql/tracker-utils.h
+++ b/src/libtracker-sparql/tracker-utils.h
@@ -20,6 +20,7 @@
#define __TRACKER_UTILS_H__
#include <glib.h>
+#include <gio/gio.h>
#include <libtracker-sparql/tracker-version.h>
TRACKER_AVAILABLE_IN_ALL
@@ -36,4 +37,8 @@ gchar* tracker_sparql_escape_string (const gchar* literal);
TRACKER_AVAILABLE_IN_ALL
gchar* tracker_sparql_get_uuid_urn (void);
+TRACKER_AVAILABLE_IN_ALL
+GFile *
+tracker_sparql_get_ontology_nepomuk (void);
+
#endif /* __TRACKER_UTILS_H__ */
diff --git a/src/tracker/tracker-sql.c b/src/tracker/tracker-sql.c
index 2d9d37f7c..533b3ccc1 100644
--- a/src/tracker/tracker-sql.c
+++ b/src/tracker/tracker-sql.c
@@ -106,7 +106,7 @@ sql_by_query (void)
db_location = g_file_new_for_commandline_arg (database_path);
data_manager = tracker_data_manager_new (TRACKER_DB_MANAGER_READONLY,
db_location, NULL,
- FALSE, 100, 100);
+ 100, 100);
if (!g_initable_init (G_INITABLE (data_manager), NULL, &error)) {
g_printerr ("%s: %s\n",
diff --git a/tests/libtracker-data/tracker-insert-or-replace-test.c b/tests/libtracker-data/tracker-insert-or-replace-test.c
index 800016631..ad6f40721 100644
--- a/tests/libtracker-data/tracker-insert-or-replace-test.c
+++ b/tests/libtracker-data/tracker-insert-or-replace-test.c
@@ -145,7 +145,7 @@ main (int argc, char *argv[])
ontology = g_file_new_for_path (TEST_ONTOLOGIES_DIR);
manager = tracker_data_manager_new (0, cache, ontology,
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
diff --git a/tests/libtracker-data/tracker-ontology-change-test.c b/tests/libtracker-data/tracker-ontology-change-test.c
index 4d15e727d..64a7023c7 100644
--- a/tests/libtracker-data/tracker-ontology-change-test.c
+++ b/tests/libtracker-data/tracker-ontology-change-test.c
@@ -212,7 +212,7 @@ test_ontology_change (void)
g_assert_cmpint (g_chmod (ontology_file, 0666), ==, 0);
manager = tracker_data_manager_new (0, data_location, test_schemas,
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
@@ -253,8 +253,7 @@ test_ontology_change (void)
g_object_unref (manager);
}
- manager = tracker_data_manager_new (0, data_location, test_schemas,
- FALSE, 100, 100);
+ manager = tracker_data_manager_new (0, data_location, test_schemas, 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
diff --git a/tests/libtracker-data/tracker-ontology-test.c b/tests/libtracker-data/tracker-ontology-test.c
index 14f6dbe89..e22078364 100644
--- a/tests/libtracker-data/tracker-ontology-test.c
+++ b/tests/libtracker-data/tracker-ontology-test.c
@@ -184,9 +184,9 @@ test_ontology_init (TestInfo *test_info,
data_location = g_file_new_for_path (test_info->data_location);
/* first-time initialization */
- manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FORCE_REINDEX,
+ manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FLAGS_NONE,
data_location, data_location,
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
@@ -194,7 +194,7 @@ test_ontology_init (TestInfo *test_info,
/* initialization from existing database */
manager = tracker_data_manager_new (0, data_location, data_location,
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
@@ -227,9 +227,9 @@ test_query (TestInfo *test_info,
g_free (ontology_path);
/* initialization */
- manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FORCE_REINDEX,
+ manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FLAGS_NONE,
data_location, ontology_location,
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
diff --git a/tests/libtracker-data/tracker-sparql-blank-test.c b/tests/libtracker-data/tracker-sparql-blank-test.c
index 5c1b269de..c49f5e428 100644
--- a/tests/libtracker-data/tracker-sparql-blank-test.c
+++ b/tests/libtracker-data/tracker-sparql-blank-test.c
@@ -53,9 +53,9 @@ test_blank (TestInfo *info,
data_location = g_file_new_for_path (info->data_location);
/* initialization */
- manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FORCE_REINDEX,
+ manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FLAGS_NONE,
data_location, data_location, /* loc, domain and ontology_name */
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index acf413823..614fc516c 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -378,10 +378,9 @@ test_sparql_query (TestInfo *test_info,
test_schemas = g_file_get_parent (file);
g_object_unref (file);
- manager = tracker_data_manager_new (TRACKER_DB_MANAGER_FORCE_REINDEX |
- TRACKER_DB_MANAGER_IN_MEMORY,
+ manager = tracker_data_manager_new (TRACKER_DB_MANAGER_IN_MEMORY,
NULL, test_schemas, /* loc, domain and ontology_name */
- FALSE, 100, 100);
+ 100, 100);
g_initable_init (G_INITABLE (manager), NULL, &error);
g_assert_no_error (error);
diff --git a/tests/libtracker-fts/tracker-fts-test.c b/tests/libtracker-fts/tracker-fts-test.c
index 0cf090422..1dbc484ff 100644
--- a/tests/libtracker-fts/tracker-fts-test.c
+++ b/tests/libtracker-fts/tracker-fts-test.c
@@ -75,8 +75,8 @@ test_sparql_query (gconstpointer test_data)
data_location = g_file_new_for_path (datadir);
conn = tracker_sparql_connection_new (TRACKER_SPARQL_CONNECTION_FLAGS_NONE,
- data_location, ontology,
- NULL, &error);
+ data_location, ontology,
+ NULL, &error);
g_assert_no_error (error);
g_object_unref (ontology);