ESourceRegistry: Do not mandate builtin sources.
[platform/upstream/evolution-data-server.git] / libedataserver / e-source-registry.c
index 7c0025f..5d2c553 100644 (file)
 #define E_SETTINGS_DEFAULT_MEMO_LIST_KEY       "default-memo-list"
 #define E_SETTINGS_DEFAULT_TASK_LIST_KEY       "default-task-list"
 
-/* This forces the GType to be registered in a way that
- * avoids a "statement with no effect" compiler warning.
- * FIXME Use g_type_ensure() once we require GLib 2.34. */
-#define REGISTER_TYPE(type) \
-       (g_type_class_unref (g_type_class_ref (type)))
-
 typedef struct _AsyncContext AsyncContext;
 typedef struct _AuthContext AuthContext;
 typedef struct _CreateContext CreateContext;
@@ -109,10 +103,10 @@ struct _ESourceRegistryPrivate {
        EDBusSourceManager *dbus_source_manager;
 
        GHashTable *object_path_table;
-       GMutex *object_path_table_lock;
+       GMutex object_path_table_lock;
 
        GHashTable *sources;
-       GMutex *sources_lock;
+       GMutex sources_lock;
 
        GSettings *settings;
 };
@@ -152,8 +146,8 @@ struct _ThreadClosure {
        ESourceRegistry *registry;
        GMainContext *main_context;
        GMainLoop *main_loop;
-       GCond *main_loop_cond;
-       GMutex *main_loop_mutex;
+       GCond main_loop_cond;
+       GMutex main_loop_mutex;
        GError *error;
 };
 
@@ -278,8 +272,8 @@ thread_closure_free (ThreadClosure *closure)
 
        g_main_context_unref (closure->main_context);
        g_main_loop_unref (closure->main_loop);
-       g_cond_free (closure->main_loop_cond);
-       g_mutex_free (closure->main_loop_mutex);
+       g_cond_clear (&closure->main_loop_cond);
+       g_mutex_clear (&closure->main_loop_mutex);
 
        /* The GError should be NULL at this point,
         * regardless of whether an error occurred. */
@@ -296,14 +290,14 @@ source_registry_object_path_table_insert (ESourceRegistry *registry,
        g_return_if_fail (object_path != NULL);
        g_return_if_fail (E_IS_SOURCE (source));
 
-       g_mutex_lock (registry->priv->object_path_table_lock);
+       g_mutex_lock (&registry->priv->object_path_table_lock);
 
        g_hash_table_insert (
                registry->priv->object_path_table,
                g_strdup (object_path),
                g_object_ref (source));
 
-       g_mutex_unlock (registry->priv->object_path_table_lock);
+       g_mutex_unlock (&registry->priv->object_path_table_lock);
 }
 
 static ESource *
@@ -314,14 +308,14 @@ source_registry_object_path_table_lookup (ESourceRegistry *registry,
 
        g_return_val_if_fail (object_path != NULL, NULL);
 
-       g_mutex_lock (registry->priv->object_path_table_lock);
+       g_mutex_lock (&registry->priv->object_path_table_lock);
 
        source = g_hash_table_lookup (
                registry->priv->object_path_table, object_path);
        if (source != NULL)
                g_object_ref (source);
 
-       g_mutex_unlock (registry->priv->object_path_table_lock);
+       g_mutex_unlock (&registry->priv->object_path_table_lock);
 
        return source;
 }
@@ -334,12 +328,12 @@ source_registry_object_path_table_remove (ESourceRegistry *registry,
 
        g_return_val_if_fail (object_path != NULL, FALSE);
 
-       g_mutex_lock (registry->priv->object_path_table_lock);
+       g_mutex_lock (&registry->priv->object_path_table_lock);
 
        removed = g_hash_table_remove (
                registry->priv->object_path_table, object_path);
 
-       g_mutex_unlock (registry->priv->object_path_table_lock);
+       g_mutex_unlock (&registry->priv->object_path_table_lock);
 
        return removed;
 }
@@ -353,13 +347,13 @@ source_registry_sources_insert (ESourceRegistry *registry,
        uid = e_source_get_uid (source);
        g_return_if_fail (uid != NULL);
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        g_hash_table_insert (
                registry->priv->sources,
                g_strdup (uid), g_object_ref (source));
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 }
 
 static gboolean
@@ -372,11 +366,11 @@ source_registry_sources_remove (ESourceRegistry *registry,
        uid = e_source_get_uid (source);
        g_return_val_if_fail (uid != NULL, FALSE);
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        removed = g_hash_table_remove (registry->priv->sources, uid);
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 
        return removed;
 }
@@ -389,14 +383,14 @@ source_registry_sources_lookup (ESourceRegistry *registry,
 
        g_return_val_if_fail (uid != NULL, NULL);
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        source = g_hash_table_lookup (registry->priv->sources, uid);
 
        if (source != NULL)
                g_object_ref (source);
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 
        return source;
 }
@@ -406,13 +400,13 @@ source_registry_sources_get_values (ESourceRegistry *registry)
 {
        GList *values;
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        values = g_hash_table_get_values (registry->priv->sources);
 
        g_list_foreach (values, (GFunc) g_object_ref, NULL);
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 
        return values;
 }
@@ -425,7 +419,7 @@ source_registry_sources_build_tree (ESourceRegistry *registry)
        GHashTableIter iter;
        gpointer key, value;
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        root = g_node_new (NULL);
        index = g_hash_table_new (g_str_hash, g_str_equal);
@@ -463,7 +457,7 @@ source_registry_sources_build_tree (ESourceRegistry *registry)
 
        g_hash_table_destroy (index);
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 
        return root;
 }
@@ -614,11 +608,11 @@ source_registry_add_source (ESourceRegistry *registry,
        uid = e_source_get_uid (source);
        g_return_if_fail (uid != NULL);
 
-       g_mutex_lock (registry->priv->sources_lock);
+       g_mutex_lock (&registry->priv->sources_lock);
 
        /* Check if we already have this source in the registry. */
        if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
-               g_mutex_unlock (registry->priv->sources_lock);
+               g_mutex_unlock (&registry->priv->sources_lock);
                return;
        }
 
@@ -632,7 +626,7 @@ source_registry_add_source (ESourceRegistry *registry,
                G_CALLBACK (source_registry_source_notify_enabled_cb),
                registry);
 
-       g_mutex_unlock (registry->priv->sources_lock);
+       g_mutex_unlock (&registry->priv->sources_lock);
 
        source_registry_sources_insert (registry, source);
 }
@@ -741,9 +735,9 @@ source_registry_object_manager_running (gpointer data)
 {
        ThreadClosure *closure = data;
 
-       g_mutex_lock (closure->main_loop_mutex);
-       g_cond_broadcast (closure->main_loop_cond);
-       g_mutex_unlock (closure->main_loop_mutex);
+       g_mutex_lock (&closure->main_loop_mutex);
+       g_cond_broadcast (&closure->main_loop_cond);
+       g_mutex_unlock (&closure->main_loop_mutex);
 
        return FALSE;
 }
@@ -991,6 +985,7 @@ source_registry_dispose (GObject *object)
        g_hash_table_remove_all (priv->sources);
 
        if (priv->settings != NULL) {
+               g_signal_handlers_disconnect_by_data (priv->settings, object);
                g_object_unref (priv->settings);
                priv->settings = NULL;
        }
@@ -1007,10 +1002,10 @@ source_registry_finalize (GObject *object)
        priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
 
        g_hash_table_destroy (priv->object_path_table);
-       g_mutex_free (priv->object_path_table_lock);
+       g_mutex_clear (&priv->object_path_table_lock);
 
        g_hash_table_destroy (priv->sources);
-       g_mutex_free (priv->sources_lock);
+       g_mutex_clear (&priv->sources_lock);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
@@ -1033,26 +1028,27 @@ source_registry_initable_init (GInitable *initable,
         * we wait for the main loop to start running as a way of
         * synchronizing with the manager thread. */
        closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
-       closure->main_loop_cond = g_cond_new ();
-       closure->main_loop_mutex = g_mutex_new ();
+       g_cond_init (&closure->main_loop_cond);
+       g_mutex_init (&closure->main_loop_mutex);
 
        registry->priv->thread_closure = closure;
 
-       registry->priv->manager_thread = g_thread_create (
+       registry->priv->manager_thread = g_thread_new (
+               NULL,
                source_registry_object_manager_thread,
-               closure, TRUE /* joinable */, error);
+               closure);
 
        if (registry->priv->manager_thread == NULL)
                return FALSE;
 
        /* Wait for notification that the manager
         * thread's main loop has been started. */
-       g_mutex_lock (closure->main_loop_mutex);
+       g_mutex_lock (&closure->main_loop_mutex);
        while (!g_main_loop_is_running (closure->main_loop))
                g_cond_wait (
-                       closure->main_loop_cond,
-                       closure->main_loop_mutex);
-       g_mutex_unlock (closure->main_loop_mutex);
+                       &closure->main_loop_cond,
+                       &closure->main_loop_mutex);
+       g_mutex_unlock (&closure->main_loop_mutex);
 
        /* Check for error in the manager thread. */
        if (closure->error != NULL) {
@@ -1061,8 +1057,24 @@ source_registry_initable_init (GInitable *initable,
                return FALSE;
        }
 
-       /* The registry should now be populated with sources. */
-       g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
+       /* The registry should now be populated with sources.
+        *
+        * XXX Actually, not necessarily if the registry service was
+        *     just now activated.  There may yet be a small window
+        *     while the registry service starts up before it exports
+        *     any sources, even built-in sources.  This COULD create
+        *     problems if any logic that depends on those built-in
+        *     sources executes during this time window, but so far
+        *     we haven't seen any cases of that.
+        *
+        *     Attempts in the past to stop and wait for sources to
+        *     show up have proven problematic.  See for example:
+        *     https://bugzilla.gnome.org/678378
+        *
+        *     Leave the runtime check disabled for the moment.
+        *     I have a feeling I'll be revisiting this again.
+        */
+       /*g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);*/
 
        /* The EDBusSourceManagerProxy is just another D-Bus interface
         * that resides at the same object path.  It's unrelated to the
@@ -1311,7 +1323,7 @@ e_source_registry_init (ESourceRegistry *registry)
                        (GDestroyNotify) g_free,
                        (GDestroyNotify) g_object_unref);
 
-       registry->priv->object_path_table_lock = g_mutex_new ();
+       g_mutex_init (&registry->priv->object_path_table_lock);
 
        /* UID string -> ESource */
        registry->priv->sources = g_hash_table_new_full (
@@ -1320,7 +1332,7 @@ e_source_registry_init (ESourceRegistry *registry)
                (GDestroyNotify) g_free,
                (GDestroyNotify) source_registry_unref_source);
 
-       registry->priv->sources_lock = g_mutex_new ();
+       g_mutex_init (&registry->priv->sources_lock);
 
        registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
 
@@ -1349,7 +1361,7 @@ e_source_registry_new_sync (GCancellable *cancellable,
        /* XXX Work around http://bugzilla.gnome.org/show_bug.cgi?id=683519
         *     until GObject's type initialization deadlock issue is fixed.
         *     Apparently only the synchronous instantiation is affected. */
-       REGISTER_TYPE (G_TYPE_DBUS_CONNECTION);
+       g_type_ensure (G_TYPE_DBUS_CONNECTION);
 
        return g_initable_new (
                E_TYPE_SOURCE_REGISTRY,
@@ -1760,6 +1772,12 @@ e_source_registry_authenticate_sync (ESourceRegistry *registry,
 
 exit:
        g_main_context_pop_thread_default (main_context);
+
+       /* Make sure the main_context doesn't have pending operations;
+          workarounds https://bugzilla.gnome.org/show_bug.cgi?id=690126 */
+       while (g_main_context_pending (main_context))
+               g_main_context_iteration (main_context, FALSE);
+
        g_main_context_unref (main_context);
 
        return success;
@@ -2725,7 +2743,6 @@ e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
 
        uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
        source = e_source_registry_ref_source (registry, uid);
-       g_return_val_if_fail (source != NULL, NULL);
 
        return source;
 }
@@ -2759,12 +2776,10 @@ e_source_registry_ref_default_address_book (ESourceRegistry *registry)
        source = e_source_registry_ref_source (registry, uid);
        g_free (uid);
 
-       /* The built-in source is always present. */
+       /* The built-in source is present in normal EDS installations. */
        if (source == NULL)
                source = e_source_registry_ref_builtin_address_book (registry);
 
-       g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
        return source;
 }
 
@@ -2827,7 +2842,6 @@ e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
 
        uid = E_SOURCE_BUILTIN_CALENDAR_UID;
        source = e_source_registry_ref_source (registry, uid);
-       g_return_val_if_fail (source != NULL, NULL);
 
        return source;
 }
@@ -2861,12 +2875,10 @@ e_source_registry_ref_default_calendar (ESourceRegistry *registry)
        source = e_source_registry_ref_source (registry, uid);
        g_free (uid);
 
-       /* The built-in source is always present. */
+       /* The built-in source is present in normal EDS installations. */
        if (source == NULL)
                source = e_source_registry_ref_builtin_calendar (registry);
 
-       g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
        return source;
 }