diff options
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); |