summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2020-11-24 14:40:05 +0000
committerSam Thursfield <sam@afuera.me.uk>2020-11-24 14:40:05 +0000
commit781cfea608757e172ddc2cb698d20498760bd7fc (patch)
treef9b3ef1d17c58582225f16d04584d8fb188f29a7
parent63879560070d8e44a24ae7feef538bde9dd7e004 (diff)
parent721c46273c48d0b5a7ce949fcbd0b5c65bd3456a (diff)
downloadtracker-781cfea608757e172ddc2cb698d20498760bd7fc.tar.gz
Merge branch 'wip/carlosg/ontology-race' into 'master'
Fix race conditions in ontology Closes #272 See merge request GNOME/tracker!343
-rw-r--r--src/libtracker-data/tracker-class.c80
-rw-r--r--src/libtracker-data/tracker-namespace.c40
-rw-r--r--src/libtracker-data/tracker-property.c255
3 files changed, 216 insertions, 159 deletions
diff --git a/src/libtracker-data/tracker-class.c b/src/libtracker-data/tracker-class.c
index 47bf8439f..c3fcdd2cd 100644
--- a/src/libtracker-data/tracker-class.c
+++ b/src/libtracker-data/tracker-class.c
@@ -35,11 +35,12 @@ struct _TrackerClassPrivate {
gchar *uri;
gchar *name;
gint id;
- gboolean is_new;
- gboolean db_schema_changed;
- gboolean notify;
+ guint is_new : 1;
+ guint db_schema_changed : 1;
+ guint notify : 1;
+ guint use_gvdb : 1;
- gboolean use_gvdb;
+ GMutex mutex;
GArray *super_classes;
GArray *domain_indexes;
@@ -73,6 +74,7 @@ tracker_class_init (TrackerClass *service)
priv->domain_indexes = g_array_new (TRUE, TRUE, sizeof (TrackerProperty *));
priv->last_domain_indexes = NULL;
priv->last_super_classes = NULL;
+ g_mutex_init (&priv->mutex);
}
static void
@@ -109,12 +111,52 @@ tracker_class_new (gboolean use_gvdb)
if (use_gvdb) {
priv = tracker_class_get_instance_private (service);
- priv->use_gvdb = use_gvdb;
+ priv->use_gvdb = !!use_gvdb;
}
return service;
}
+static void
+tracker_class_maybe_sync_from_gvdb (TrackerClass *service)
+{
+ TrackerClassPrivate *priv;
+ TrackerClass *super_class;
+ GVariant *variant;
+
+ priv = tracker_class_get_instance_private (service);
+
+ if (!priv->use_gvdb)
+ return;
+
+ g_mutex_lock (&priv->mutex);
+
+ /* In case the lock was contended, make the second lose */
+ if (!priv->use_gvdb)
+ goto out;
+
+ tracker_class_reset_super_classes (service);
+
+ variant = tracker_ontologies_get_class_value_gvdb (priv->ontologies, priv->uri, "super-classes");
+ if (variant) {
+ GVariantIter iter;
+ const gchar *uri;
+
+ g_variant_iter_init (&iter, variant);
+ while (g_variant_iter_loop (&iter, "&s", &uri)) {
+ super_class = tracker_ontologies_get_class_by_uri (priv->ontologies, uri);
+
+ tracker_class_add_super_class (service, super_class);
+ }
+
+ g_variant_unref (variant);
+ }
+
+ priv->use_gvdb = FALSE;
+out:
+ g_mutex_unlock (&priv->mutex);
+}
+
const gchar *
tracker_class_get_uri (TrackerClass *service)
{
@@ -160,27 +202,7 @@ tracker_class_get_super_classes (TrackerClass *service)
priv = tracker_class_get_instance_private (service);
- if (priv->use_gvdb) {
- TrackerClass *super_class;
- GVariant *variant;
-
- tracker_class_reset_super_classes (service);
-
- variant = tracker_ontologies_get_class_value_gvdb (priv->ontologies, priv->uri, "super-classes");
- if (variant) {
- GVariantIter iter;
- const gchar *uri;
-
- g_variant_iter_init (&iter, variant);
- while (g_variant_iter_loop (&iter, "&s", &uri)) {
- super_class = tracker_ontologies_get_class_by_uri (priv->ontologies, uri);
-
- tracker_class_add_super_class (service, super_class);
- }
-
- g_variant_unref (variant);
- }
- }
+ tracker_class_maybe_sync_from_gvdb (service);
return (TrackerClass **) priv->super_classes->data;
}
@@ -407,7 +429,7 @@ tracker_class_set_is_new (TrackerClass *service,
priv = tracker_class_get_instance_private (service);
- priv->is_new = value;
+ priv->is_new = !!value;
}
@@ -421,7 +443,7 @@ tracker_class_set_notify (TrackerClass *service,
priv = tracker_class_get_instance_private (service);
- priv->notify = value;
+ priv->notify = !!value;
}
void
@@ -434,7 +456,7 @@ tracker_class_set_db_schema_changed (TrackerClass *service,
priv = tracker_class_get_instance_private (service);
- priv->db_schema_changed = value;
+ priv->db_schema_changed = !!value;
}
void
diff --git a/src/libtracker-data/tracker-namespace.c b/src/libtracker-data/tracker-namespace.c
index 618570062..6cbb1085e 100644
--- a/src/libtracker-data/tracker-namespace.c
+++ b/src/libtracker-data/tracker-namespace.c
@@ -32,10 +32,11 @@ typedef struct _TrackerNamespacePrivate TrackerNamespacePrivate;
struct _TrackerNamespacePrivate {
gchar *uri;
- gboolean use_gvdb;
+ GMutex mutex;
+ guint use_gvdb : 1;
+ guint is_new : 1;
gchar *prefix;
- gboolean is_new;
TrackerOntologies *ontologies;
};
@@ -54,6 +55,10 @@ tracker_namespace_class_init (TrackerNamespaceClass *klass)
static void
tracker_namespace_init (TrackerNamespace *service)
{
+ TrackerNamespacePrivate *priv;
+
+ priv = tracker_namespace_get_instance_private (service);
+ g_mutex_init (&priv->mutex);
}
static void
@@ -79,12 +84,35 @@ tracker_namespace_new (gboolean use_gvdb)
if (use_gvdb) {
priv = tracker_namespace_get_instance_private (namespace);
- priv->use_gvdb = use_gvdb;
+ priv->use_gvdb = !!use_gvdb;
}
return namespace;
}
+static void
+tracker_namespace_maybe_sync_from_gvdb (TrackerNamespace *namespace)
+{
+ TrackerNamespacePrivate *priv;
+
+ priv = tracker_namespace_get_instance_private (namespace);
+
+ if (!priv->use_gvdb)
+ return;
+
+ g_mutex_lock (&priv->mutex);
+
+ /* In case the lock was contended, make the second lose */
+ if (!priv->use_gvdb)
+ goto out;
+
+ priv->prefix = g_strdup (tracker_ontologies_get_namespace_string_gvdb (priv->ontologies, priv->uri, "prefix"));
+
+ priv->use_gvdb = FALSE;
+out:
+ g_mutex_unlock (&priv->mutex);
+}
+
const gchar *
tracker_namespace_get_uri (TrackerNamespace *namespace)
{
@@ -106,9 +134,7 @@ tracker_namespace_get_prefix (TrackerNamespace *namespace)
priv = tracker_namespace_get_instance_private (namespace);
- if (!priv->prefix && priv->use_gvdb) {
- priv->prefix = g_strdup (tracker_ontologies_get_namespace_string_gvdb (priv->ontologies, priv->uri, "prefix"));
- }
+ tracker_namespace_maybe_sync_from_gvdb (namespace);
return priv->prefix;
}
@@ -173,7 +199,7 @@ tracker_namespace_set_is_new (TrackerNamespace *namespace,
priv = tracker_namespace_get_instance_private (namespace);
- priv->is_new = value;
+ priv->is_new = !!value;
}
void
diff --git a/src/libtracker-data/tracker-property.c b/src/libtracker-data/tracker-property.c
index b6f21c0fb..df72b27cc 100644
--- a/src/libtracker-data/tracker-property.c
+++ b/src/libtracker-data/tracker-property.c
@@ -44,8 +44,7 @@ struct _TrackerPropertyPrivate {
gchar *uri;
gchar *name;
gchar *table_name;
-
- gboolean use_gvdb;
+ GMutex mutex;
TrackerPropertyType data_type;
TrackerClass *domain;
@@ -53,24 +52,26 @@ struct _TrackerPropertyPrivate {
TrackerClass *range;
gint weight;
gint id;
- gboolean indexed;
+ guint use_gvdb : 1;
+ guint indexed : 1;
+ guint orig_fulltext_indexed : 1;
+ guint fulltext_indexed : 1;
+ guint multiple_values : 1;
+ guint last_multiple_values : 1;
+ guint is_inverse_functional_property : 1;
+ guint is_new : 1;
+ guint db_schema_changed : 1;
+ guint writeback : 1;
+ guint force_journal : 1;
+ guint cardinality_changed : 1;
+ guint orig_multiple_values : 1;
+
TrackerProperty *secondary_index;
- gboolean orig_fulltext_indexed;
- gboolean fulltext_indexed;
- gboolean multiple_values;
- gboolean last_multiple_values;
- gboolean is_inverse_functional_property;
- gboolean is_new;
- gboolean db_schema_changed;
- gboolean writeback;
GPtrArray *is_new_domain_index;
- gboolean force_journal;
GArray *super_properties;
GArray *domain_indexes;
GArray *last_super_properties;
- gboolean cardinality_changed;
- gboolean orig_multiple_values;
TrackerOntologies *ontologies;
};
@@ -145,6 +146,7 @@ tracker_property_init (TrackerProperty *property)
priv->domain_indexes = g_array_new (TRUE, TRUE, sizeof (TrackerClass *));
priv->last_super_properties = NULL;
priv->cardinality_changed = FALSE;
+ g_mutex_init (&priv->mutex);
}
static void
@@ -201,12 +203,109 @@ tracker_property_new (gboolean use_gvdb)
if (use_gvdb) {
priv = tracker_property_get_instance_private (property);
- priv->use_gvdb = use_gvdb;
+ priv->use_gvdb = !!use_gvdb;
}
return property;
}
+static void
+tracker_property_maybe_sync_from_gvdb (TrackerProperty *property)
+{
+ TrackerPropertyPrivate *priv;
+ GVariant *variant;
+ const gchar *range_uri;
+ const gchar *domain_uri;
+ TrackerClass *domain_index;
+
+ priv = tracker_property_get_instance_private (property);
+
+ if (!priv->use_gvdb)
+ return;
+
+ g_mutex_lock (&priv->mutex);
+
+ /* In case the lock was contended, make the second lose */
+ if (!priv->use_gvdb)
+ goto out;
+
+ /* Data type */
+ range_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "range");
+ if (strcmp (range_uri, XSD_STRING) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_STRING;
+ } else if (strcmp (range_uri, RDF_LANGSTRING) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_LANGSTRING;
+ } else if (strcmp (range_uri, XSD_BOOLEAN) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
+ } else if (strcmp (range_uri, XSD_INTEGER) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_INTEGER;
+ } else if (strcmp (range_uri, XSD_DOUBLE) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_DOUBLE;
+ } else if (strcmp (range_uri, XSD_DATE) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_DATE;
+ } else if (strcmp (range_uri, XSD_DATETIME) == 0) {
+ priv->data_type = TRACKER_PROPERTY_TYPE_DATETIME;
+ } else {
+ priv->data_type = TRACKER_PROPERTY_TYPE_RESOURCE;
+ }
+
+ /* Range */
+ priv->range = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, range_uri));
+
+ /* Domain */
+ domain_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "domain");
+ priv->domain = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, domain_uri));
+
+ /* Domain indexes */
+ tracker_property_reset_domain_indexes (property);
+
+ variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "domain-indexes");
+ if (variant) {
+ GVariantIter iter;
+ const gchar *uri;
+
+ g_variant_iter_init (&iter, variant);
+ while (g_variant_iter_loop (&iter, "&s", &uri)) {
+ domain_index = tracker_ontologies_get_class_by_uri (priv->ontologies, uri);
+
+ tracker_property_add_domain_index (property, domain_index);
+ }
+
+ g_variant_unref (variant);
+ }
+
+ /* Fulltext indexed */
+ variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "fulltext-indexed");
+ if (variant != NULL) {
+ priv->fulltext_indexed = g_variant_get_boolean (variant);
+ g_variant_unref (variant);
+ } else {
+ priv->fulltext_indexed = FALSE;
+ }
+
+ /* Cardinality */
+ variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "max-cardinality");
+ if (variant != NULL) {
+ priv->multiple_values = FALSE;
+ g_variant_unref (variant);
+ } else {
+ priv->multiple_values = TRUE;
+ }
+
+ /* Inverse functional property */
+ variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "inverse-functional");
+ if (variant != NULL) {
+ priv->is_inverse_functional_property = g_variant_get_boolean (variant);
+ g_variant_unref (variant);
+ } else {
+ priv->is_inverse_functional_property = FALSE;
+ }
+
+ priv->use_gvdb = FALSE;
+out:
+ g_mutex_unlock (&priv->mutex);
+}
+
const gchar *
tracker_property_get_uri (TrackerProperty *property)
{
@@ -262,28 +361,7 @@ tracker_property_get_data_type (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (priv->use_gvdb) {
- const gchar *range_uri;
-
- range_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "range");
- if (strcmp (range_uri, XSD_STRING) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_STRING;
- } else if (strcmp (range_uri, RDF_LANGSTRING) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_LANGSTRING;
- } else if (strcmp (range_uri, XSD_BOOLEAN) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
- } else if (strcmp (range_uri, XSD_INTEGER) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_INTEGER;
- } else if (strcmp (range_uri, XSD_DOUBLE) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_DOUBLE;
- } else if (strcmp (range_uri, XSD_DATE) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_DATE;
- } else if (strcmp (range_uri, XSD_DATETIME) == 0) {
- priv->data_type = TRACKER_PROPERTY_TYPE_DATETIME;
- } else {
- priv->data_type = TRACKER_PROPERTY_TYPE_RESOURCE;
- }
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->data_type;
}
@@ -300,12 +378,7 @@ tracker_property_get_domain (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (!priv->domain && priv->use_gvdb) {
- const gchar *domain_uri;
-
- domain_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "domain");
- priv->domain = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, domain_uri));
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->domain;
}
@@ -322,27 +395,7 @@ tracker_property_get_domain_indexes (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (priv->use_gvdb) {
- TrackerClass *domain_index;
- GVariant *variant;
-
- tracker_property_reset_domain_indexes (property);
-
- variant = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "domain-indexes");
- if (variant) {
- GVariantIter iter;
- const gchar *uri;
-
- g_variant_iter_init (&iter, variant);
- while (g_variant_iter_loop (&iter, "&s", &uri)) {
- domain_index = tracker_ontologies_get_class_by_uri (priv->ontologies, uri);
-
- tracker_property_add_domain_index (property, domain_index);
- }
-
- g_variant_unref (variant);
- }
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return (TrackerClass ** ) priv->domain_indexes->data;
}
@@ -387,12 +440,7 @@ tracker_property_get_range (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (!priv->range && priv->use_gvdb) {
- const gchar *range_uri;
-
- range_uri = tracker_ontologies_get_property_string_gvdb (priv->ontologies, priv->uri, "range");
- priv->range = g_object_ref (tracker_ontologies_get_class_by_uri (priv->ontologies, range_uri));
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->range;
}
@@ -457,20 +505,7 @@ tracker_property_get_fulltext_indexed (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (priv->use_gvdb) {
- GVariant *value;
- gboolean result;
-
- value = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "fulltext-indexed");
- if (value != NULL) {
- result = g_variant_get_boolean (value);
- g_variant_unref (value);
- } else {
- result = FALSE;
- }
-
- return result;
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->fulltext_indexed;
}
@@ -569,20 +604,7 @@ tracker_property_get_multiple_values (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (priv->use_gvdb) {
- GVariant *value;
- gboolean result;
-
- value = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "max-cardinality");
- if (value != NULL) {
- result = FALSE;
- g_variant_unref (value);
- } else {
- result = TRUE;
- }
-
- return result;
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->multiple_values;
}
@@ -620,20 +642,7 @@ tracker_property_get_is_inverse_functional_property (TrackerProperty *property)
priv = tracker_property_get_instance_private (property);
- if (priv->use_gvdb) {
- GVariant *value;
- gboolean result;
-
- value = tracker_ontologies_get_property_value_gvdb (priv->ontologies, priv->uri, "inverse-functional");
- if (value != NULL) {
- result = g_variant_get_boolean (value);
- g_variant_unref (value);
- } else {
- result = FALSE;
- }
-
- return result;
- }
+ tracker_property_maybe_sync_from_gvdb (property);
return priv->is_inverse_functional_property;
}
@@ -858,7 +867,7 @@ tracker_property_set_indexed (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->indexed = value;
+ priv->indexed = !!value;
}
void
@@ -871,7 +880,7 @@ tracker_property_set_is_new (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->is_new = value;
+ priv->is_new = !!value;
}
void
@@ -931,7 +940,7 @@ tracker_property_set_writeback (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->writeback = value;
+ priv->writeback = !!value;
}
void
@@ -944,7 +953,7 @@ tracker_property_set_db_schema_changed (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->db_schema_changed = value;
+ priv->db_schema_changed = !!value;
}
void
@@ -957,7 +966,7 @@ tracker_property_set_cardinality_changed (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->cardinality_changed = value;
+ priv->cardinality_changed = !!value;
}
void
@@ -970,7 +979,7 @@ tracker_property_set_orig_fulltext_indexed (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->orig_fulltext_indexed = value;
+ priv->orig_fulltext_indexed = !!value;
}
void
@@ -983,7 +992,7 @@ tracker_property_set_fulltext_indexed (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->fulltext_indexed = value;
+ priv->fulltext_indexed = !!value;
}
void
@@ -996,7 +1005,7 @@ tracker_property_set_multiple_values (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->multiple_values = value;
+ priv->multiple_values = !!value;
g_clear_pointer (&priv->table_name, g_free);
}
@@ -1010,7 +1019,7 @@ tracker_property_set_last_multiple_values (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->last_multiple_values = value;
+ priv->last_multiple_values = !!value;
}
void
@@ -1023,7 +1032,7 @@ tracker_property_set_orig_multiple_values (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->orig_multiple_values = value;
+ priv->orig_multiple_values = !!value;
}
@@ -1037,7 +1046,7 @@ tracker_property_set_is_inverse_functional_property (TrackerProperty *property,
priv = tracker_property_get_instance_private (property);
- priv->is_inverse_functional_property = value;
+ priv->is_inverse_functional_property = !!value;
}
void