diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2020-11-24 14:40:05 +0000 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2020-11-24 14:40:05 +0000 |
commit | 781cfea608757e172ddc2cb698d20498760bd7fc (patch) | |
tree | f9b3ef1d17c58582225f16d04584d8fb188f29a7 | |
parent | 63879560070d8e44a24ae7feef538bde9dd7e004 (diff) | |
parent | 721c46273c48d0b5a7ce949fcbd0b5c65bd3456a (diff) | |
download | tracker-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.c | 80 | ||||
-rw-r--r-- | src/libtracker-data/tracker-namespace.c | 40 | ||||
-rw-r--r-- | src/libtracker-data/tracker-property.c | 255 |
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 |