[evolution-data-server] [EDBusServer] Load newly added modules on the fly



commit 07086740ba1c51779e310087f9c77474978a7463
Author: Milan Crha <mcrha redhat com>
Date:   Fri Nov 20 13:03:48 2015 +0100

    [EDBusServer] Load newly added modules on the fly
    
    This is to cover situation when user installs a new 3rd-party modules
    with background processes running, then runs evolution and adds
    an account for the installed module, but the Evolution didn't show
    anything, until the background processes were restarted.

 addressbook/libedata-book/e-data-book-factory.c    |    3 +-
 calendar/libedata-cal/e-data-cal-factory.c         |    3 +-
 libebackend/e-data-factory.c                       |   18 +++---
 libebackend/e-dbus-server.c                        |   65 ++++++++++++++++++++
 modules/google-backend/module-google-backend.c     |    9 ++-
 modules/owncloud-backend/module-owncloud-backend.c |    9 ++-
 .../evolution-addressbook-factory.c                |    9 +++-
 .../evolution-calendar-factory.c                   |    9 +++-
 .../evolution-user-prompter.c                      |    9 +++-
 9 files changed, 115 insertions(+), 19 deletions(-)
---
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index 3dc4574..7b247de 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -194,5 +194,6 @@ e_data_book_factory_new (GCancellable *cancellable,
 {
        return g_initable_new (
                E_TYPE_DATA_BOOK_FACTORY,
-               cancellable, error, NULL);
+               cancellable, error,
+               "reload-supported", TRUE, NULL);
 }
diff --git a/calendar/libedata-cal/e-data-cal-factory.c b/calendar/libedata-cal/e-data-cal-factory.c
index 57f897f..aad7914 100644
--- a/calendar/libedata-cal/e-data-cal-factory.c
+++ b/calendar/libedata-cal/e-data-cal-factory.c
@@ -302,5 +302,6 @@ e_data_cal_factory_new (GCancellable *cancellable,
 
        return g_initable_new (
                E_TYPE_DATA_CAL_FACTORY,
-               cancellable, error, NULL);
+               cancellable, error,
+               "reload-supported", TRUE, NULL);
 }
diff --git a/libebackend/e-data-factory.c b/libebackend/e-data-factory.c
index 1f3880e..80ecd9d 100644
--- a/libebackend/e-data-factory.c
+++ b/libebackend/e-data-factory.c
@@ -637,11 +637,12 @@ data_factory_subprocess_vanished_cb (GDBusConnection *connection,
 {
        DataFactorySubprocessData *sd;
        DataFactorySubprocessHelper *helper;
+       EDataFactory *data_factory;
        EDataFactoryPrivate *priv;
        const gchar *sender;
-       guint watched_id;
 
        sd = user_data;
+       data_factory = g_object_ref (sd->data_factory);
        priv = sd->data_factory->priv;
 
        g_mutex_lock (&priv->mutex);
@@ -650,8 +651,10 @@ data_factory_subprocess_vanished_cb (GDBusConnection *connection,
                sd->subprocess_helpers_hash_key);
        g_mutex_unlock (&priv->mutex);
 
-       if (helper == NULL)
+       if (helper == NULL) {
+               g_clear_object (&data_factory);
                return;
+       }
 
        sender = g_dbus_method_invocation_get_sender (sd->invocation);
        data_factory_connections_remove (sd->data_factory, sender, helper->proxy);
@@ -663,12 +666,10 @@ data_factory_subprocess_vanished_cb (GDBusConnection *connection,
        g_mutex_unlock (&priv->mutex);
 
        g_mutex_lock (&priv->subprocess_watched_ids_lock);
-       watched_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->subprocess_watched_ids, sd->bus_name));
        g_hash_table_remove (priv->subprocess_watched_ids, sd->bus_name);
-
-       if (watched_id > 0)
-               g_bus_unwatch_name (watched_id);
        g_mutex_unlock (&priv->subprocess_watched_ids_lock);
+
+       g_clear_object (&data_factory);
 }
 
 static void
@@ -1052,7 +1053,7 @@ e_data_factory_init (EDataFactory *data_factory)
                (GHashFunc) g_str_hash,
                (GEqualFunc) g_str_equal,
                (GDestroyNotify) g_free,
-               (GDestroyNotify) NULL);
+               (GDestroyNotify) watched_names_value_free);
 
        data_factory->priv->connections = g_hash_table_new_full (
                (GHashFunc) g_str_hash,
@@ -1298,7 +1299,8 @@ data_factory_spawn_subprocess_backend (EDataFactory *data_factory,
 
                if (sd) {
                        g_mutex_lock (&priv->subprocess_watched_ids_lock);
-                       g_hash_table_remove (priv->subprocess_watched_ids, sd->bus_name);
+                       if (g_hash_table_remove (priv->subprocess_watched_ids, sd->bus_name))
+                               watched_id = 0;
                        g_mutex_unlock (&priv->subprocess_watched_ids_lock);
                }
 
diff --git a/libebackend/e-dbus-server.c b/libebackend/e-dbus-server.c
index 646e592..a801760 100644
--- a/libebackend/e-dbus-server.c
+++ b/libebackend/e-dbus-server.c
@@ -51,6 +51,8 @@ struct _EDBusServerPrivate {
        EDBusServerExitCode exit_code;
 
        GMutex property_lock;
+
+       GFileMonitor *directory_monitor;
 };
 
 enum {
@@ -157,6 +159,17 @@ dbus_server_finalize (GObject *object)
 }
 
 static void
+dbus_server_dispose (GObject *object)
+{
+       EDBusServer *server = E_DBUS_SERVER (object);
+
+       g_clear_object (&server->priv->directory_monitor);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_dbus_server_parent_class)->dispose (object);
+}
+
+static void
 dbus_server_constructed (GObject *object)
 {
        e_dbus_server_load_modules (E_DBUS_SERVER (object));
@@ -273,6 +286,7 @@ e_dbus_server_class_init (EDBusServerClass *class)
 
        object_class = G_OBJECT_CLASS (class);
        object_class->finalize = dbus_server_finalize;
+       object_class->dispose = dbus_server_dispose;
        object_class->constructed = dbus_server_constructed;
 
        class->bus_acquired = dbus_server_bus_acquired;
@@ -508,6 +522,44 @@ e_dbus_server_release (EDBusServer *server)
        g_mutex_unlock (&server->priv->property_lock);
 }
 
+static void
+dbus_server_module_directory_changed_cb (GFileMonitor *monitor,
+                                        GFile *file,
+                                        GFile *other_file,
+                                        GFileMonitorEvent event_type,
+                                        gpointer user_data)
+{
+       EDBusServer *server;
+
+       g_return_if_fail (E_IS_DBUS_SERVER (user_data));
+
+       server = E_DBUS_SERVER (user_data);
+
+       if (event_type == G_FILE_MONITOR_EVENT_CREATED ||
+           event_type == G_FILE_MONITOR_EVENT_DELETED ||
+           event_type == G_FILE_MONITOR_EVENT_MOVED_IN ||
+           event_type == G_FILE_MONITOR_EVENT_MOVED_OUT) {
+               gchar *filename;
+
+               filename = g_file_get_path (file);
+
+               if (filename && g_str_has_suffix (filename, "." G_MODULE_SUFFIX)) {
+                       if (event_type == G_FILE_MONITOR_EVENT_CREATED ||
+                           event_type == G_FILE_MONITOR_EVENT_MOVED_IN) {
+                               EModule *module;
+
+                               module = e_module_load_file (filename);
+                               if (module)
+                                       g_type_module_unuse ((GTypeModule *) module);
+                       }
+
+                       e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_RELOAD);
+               }
+
+               g_free (filename);
+       }
+}
+
 /**
  * e_dbus_server_load_modules:
  * @server: an #EDBusServer
@@ -539,6 +591,19 @@ e_dbus_server_load_modules (EDBusServer *server)
        g_hash_table_add (directories_loaded, (gpointer) directory);
        G_UNLOCK (directories_loaded);
 
+       if (!server->priv->directory_monitor) {
+               GFile *dir_file;
+
+               dir_file = g_file_new_for_path (class->module_directory);
+               server->priv->directory_monitor = g_file_monitor_directory (dir_file, 
G_FILE_MONITOR_WATCH_MOVES, NULL, NULL);
+               g_clear_object (&dir_file);
+
+               if (server->priv->directory_monitor) {
+                       g_signal_connect (server->priv->directory_monitor, "changed",
+                               G_CALLBACK (dbus_server_module_directory_changed_cb), server);
+               }
+       }
+
        if (already_loaded)
                return;
 
diff --git a/modules/google-backend/module-google-backend.c b/modules/google-backend/module-google-backend.c
index 8ab4b2f..529f519 100644
--- a/modules/google-backend/module-google-backend.c
+++ b/modules/google-backend/module-google-backend.c
@@ -332,6 +332,8 @@ google_add_found_source (ECollectionBackend *collection,
        g_return_if_fail (backend_name != NULL);
 
        server = e_collection_backend_ref_server (collection);
+       if (!server)
+               return;
 
        url = soup_uri_to_string (uri, FALSE);
        identity = g_strconcat (identity_prefix, "::", url, NULL);
@@ -510,9 +512,10 @@ google_backend_authenticate_sync (EBackend *backend,
 
                server = e_collection_backend_ref_server (collection);
 
-               g_hash_table_foreach (known_sources, google_remove_unknown_sources_cb, server);
-
-               g_object_unref (server);
+               if (server) {
+                       g_hash_table_foreach (known_sources, google_remove_unknown_sources_cb, server);
+                       g_object_unref (server);
+               }
        }
 
        if (local_error == NULL) {
diff --git a/modules/owncloud-backend/module-owncloud-backend.c 
b/modules/owncloud-backend/module-owncloud-backend.c
index 6315d0d..238cd7e 100644
--- a/modules/owncloud-backend/module-owncloud-backend.c
+++ b/modules/owncloud-backend/module-owncloud-backend.c
@@ -169,6 +169,8 @@ owncloud_add_found_source (ECollectionBackend *collection,
        g_return_if_fail (backend_name != NULL);
 
        server = e_collection_backend_ref_server (collection);
+       if (!server)
+               return;
 
        url = soup_uri_to_string (uri, FALSE);
        identity = g_strconcat (identity_prefix, "::", url, NULL);
@@ -376,9 +378,10 @@ owncloud_backend_authenticate_sync (EBackend *backend,
 
                server = e_collection_backend_ref_server (collection);
 
-               g_hash_table_foreach (known_sources, owncloud_remove_unknown_sources_cb, server);
-
-               g_object_unref (server);
+               if (server) {
+                       g_hash_table_foreach (known_sources, owncloud_remove_unknown_sources_cb, server);
+                       g_object_unref (server);
+               }
        }
 
        if (local_error == NULL) {
diff --git a/services/evolution-addressbook-factory/evolution-addressbook-factory.c 
b/services/evolution-addressbook-factory/evolution-addressbook-factory.c
index 3d9cdb6..08ed333 100644
--- a/services/evolution-addressbook-factory/evolution-addressbook-factory.c
+++ b/services/evolution-addressbook-factory/evolution-addressbook-factory.c
@@ -45,6 +45,7 @@ main (gint argc,
 {
        GOptionContext *context;
        EDBusServer *server;
+       EDBusServerExitCode exit_code;
        GError *error = NULL;
 
 #ifdef G_OS_WIN32
@@ -77,6 +78,7 @@ main (gint argc,
 
        e_gdbus_templates_init_main_thread ();
 
+ reload:
        server = e_data_book_factory_new (NULL, &error);
 
        if (error != NULL) {
@@ -91,10 +93,15 @@ main (gint argc,
        if (opt_keep_running)
                e_dbus_server_hold (server);
 
-       e_dbus_server_run (server, opt_wait_for_client);
+       exit_code = e_dbus_server_run (server, opt_wait_for_client);
 
        g_object_unref (server);
 
+       if (exit_code == E_DBUS_SERVER_EXIT_RELOAD) {
+               g_debug ("Reloading...");
+               goto reload;
+       }
+
        g_debug ("Bye.");
 
        return 0;
diff --git a/services/evolution-calendar-factory/evolution-calendar-factory.c 
b/services/evolution-calendar-factory/evolution-calendar-factory.c
index 50ae308..ea7d952 100644
--- a/services/evolution-calendar-factory/evolution-calendar-factory.c
+++ b/services/evolution-calendar-factory/evolution-calendar-factory.c
@@ -49,6 +49,7 @@ main (gint argc,
 {
        GOptionContext *context;
        EDBusServer *server;
+       EDBusServerExitCode exit_code;
        GError *error = NULL;
 
 #ifdef G_OS_WIN32
@@ -85,6 +86,7 @@ main (gint argc,
 
        e_gdbus_templates_init_main_thread ();
 
+ reload:
        server = e_data_cal_factory_new (NULL, &error);
 
        if (error != NULL) {
@@ -99,10 +101,15 @@ main (gint argc,
        if (opt_keep_running)
                e_dbus_server_hold (server);
 
-       e_dbus_server_run (server, opt_wait_for_client);
+       exit_code = e_dbus_server_run (server, opt_wait_for_client);
 
        g_object_unref (server);
 
+       if (exit_code == E_DBUS_SERVER_EXIT_RELOAD) {
+               g_debug ("Reloading...");
+               goto reload;
+       }
+
        g_debug ("Bye.");
 
        return 0;
diff --git a/services/evolution-user-prompter/evolution-user-prompter.c 
b/services/evolution-user-prompter/evolution-user-prompter.c
index b97778e..21d1ad2 100644
--- a/services/evolution-user-prompter/evolution-user-prompter.c
+++ b/services/evolution-user-prompter/evolution-user-prompter.c
@@ -39,6 +39,7 @@ main (gint argc,
 {
        GOptionContext *context;
        EDBusServer *server;
+       EDBusServerExitCode exit_code;
        GError *error = NULL;
 
 #ifdef G_OS_WIN32
@@ -66,6 +67,7 @@ main (gint argc,
 
        e_gdbus_templates_init_main_thread ();
 
+ reload:
        server = e_user_prompter_server_new ();
        g_signal_connect (
                server, "prompt",
@@ -78,10 +80,15 @@ main (gint argc,
        if (opt_keep_running)
                e_dbus_server_hold (server);
 
-       e_dbus_server_run (server, TRUE);
+       exit_code = e_dbus_server_run (server, TRUE);
 
        g_object_unref (server);
 
+       if (exit_code == E_DBUS_SERVER_EXIT_RELOAD) {
+               g_debug ("Reloading...");
+               goto reload;
+       }
+
        g_debug ("Bye.");
 
        return 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]