Fix for bug NB#83343
authorJose Dapena Paz <jdapena@igalia.com>
Mon, 26 May 2008 16:29:18 +0000 (16:29 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Mon, 26 May 2008 16:29:18 +0000 (16:29 +0000)
* src/modest-mail-operation-queue.[ch]:
        * Add the special handling for shutdown sync mail operation.
          This operation should be requested everytime we decide that
          modest should be finished (mail operation queue is empty, and
          no windows displayed). If queue exhaust again, and the last
          operation finished was that shutdown sync, then we can close
          modest safely. This way we don't have to sync on shutdown
          process itself.
* src/modest-main.c:
        * On (on_idle_exit_modest) handler implement checking for last
          operation. If last operation was the shutdown sync then we
          close silently. If not then we have to run the operation.
* src/modest-init.c:
        * Move to the last shutdown step the gnome vfs shutdown.
* src/modest-mail-operation.[ch]:
        * Add shutdown mail operation. This simply syncs all accounts
* src/modest-tny-account-store.[ch]:
        * New async method that shutdowns all accounts in a store.
        * Now the finalize of the account store does not shutdown the
          accounts as this step should have happened before.

pmo-trunk-r4572

src/modest-init.c
src/modest-mail-operation-queue.c
src/modest-mail-operation-queue.h
src/modest-mail-operation.c
src/modest-mail-operation.h
src/modest-main.c
src/modest-tny-account-store.c
src/modest-tny-account-store.h

index e3f54de..c06fae9 100644 (file)
@@ -297,15 +297,15 @@ modest_init_uninit (void)
        if (!_is_initialized)
                return TRUE; 
        
-       if (gnome_vfs_initialized()) /* apparently, this returns TRUE, even after a shutdown */
-               gnome_vfs_shutdown ();
-               
        if (!modest_runtime_uninit())
                g_printerr ("modest: failed to uninit runtime\n");
 
        if (!modest_platform_uninit())
                g_printerr ("modest: failed to uninit platform\n");
        
+       if (gnome_vfs_initialized()) /* apparently, this returns TRUE, even after a shutdown */
+               gnome_vfs_shutdown ();
+               
        _is_initialized = FALSE;
        return TRUE;
 }
index aadb3b8..804a656 100644 (file)
@@ -55,6 +55,7 @@ struct _ModestMailOperationQueuePrivate {
        GMutex *queue_lock;
        guint   op_id;
        guint   queue_empty_handler;
+       gboolean running_final_sync;
 };
 #define MODEST_MAIL_OPERATION_QUEUE_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                          MODEST_TYPE_MAIL_OPERATION_QUEUE, \
@@ -148,6 +149,7 @@ modest_mail_operation_queue_init (ModestMailOperationQueue *obj)
        priv->queue_lock = g_mutex_new ();
        priv->op_id = 0;
        priv->queue_empty_handler = 0;
+       priv->running_final_sync = FALSE;
 }
 
 static void
@@ -246,6 +248,8 @@ modest_mail_operation_queue_add (ModestMailOperationQueue *self,
        
        priv = MODEST_MAIL_OPERATION_QUEUE_GET_PRIVATE(self);
 
+       priv->running_final_sync = (modest_mail_operation_get_type_operation (mail_op) == MODEST_MAIL_OPERATION_TYPE_SHUTDOWN);
+
        g_mutex_lock (priv->queue_lock);
        g_queue_push_tail (priv->op_queue, g_object_ref (mail_op));
        g_mutex_unlock (priv->queue_lock);
@@ -512,3 +516,25 @@ modest_mail_operation_queue_to_string (ModestMailOperationQueue *self)
                
        return str;
 }
+
+gboolean
+modest_mail_operation_queue_running_shutdown (ModestMailOperationQueue *self)
+{
+       ModestMailOperationQueuePrivate *priv;
+       
+       g_return_val_if_fail (MODEST_IS_MAIL_OPERATION_QUEUE (self), FALSE);
+       
+       priv = MODEST_MAIL_OPERATION_QUEUE_GET_PRIVATE(self);
+       return priv->running_final_sync;
+}
+
+void
+modest_mail_operation_queue_set_running_shutdown (ModestMailOperationQueue *self)
+{
+       ModestMailOperationQueuePrivate *priv;
+       
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION_QUEUE (self));
+       
+       priv = MODEST_MAIL_OPERATION_QUEUE_GET_PRIVATE(self);
+       priv->running_final_sync = TRUE;
+}
index 0a1e08f..4171306 100644 (file)
@@ -142,6 +142,28 @@ GSList* modest_mail_operation_queue_get_by_source (ModestMailOperationQueue *op_
  **/
 gchar* modest_mail_operation_queue_to_string (ModestMailOperationQueue *self);
 
+/**
+ * modest_mail_operation_queue_set_running_shutdown:
+ * @self: a #ModestMailOperationQueue
+ *
+ * Mark the queue as running the final sync.
+ *
+ */
+void
+modest_mail_operation_queue_set_running_shutdown (ModestMailOperationQueue *self);
+
+/**
+ * modest_mail_operation_queue_running_shutdown:
+ * @self: a #ModestMailOperationQueue
+ *
+ * Is the last operation queued a shutdown operation?
+ *
+ * Returns: a #gboolean, %TRUE if the last queued operation is
+ * a shutdown, %FALSE otherwise
+ */
+gboolean
+modest_mail_operation_queue_running_shutdown (ModestMailOperationQueue *self);
+
 G_END_DECLS
 
 #endif /* __MODEST_MAIL_OPERATION_QUEUE_H__ */
index 7c518d4..64afda8 100644 (file)
@@ -3132,6 +3132,7 @@ run_queue_stop (ModestTnySendQueue *queue,
        g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
        g_object_unref (self);
 }
+
 void
 modest_mail_operation_run_queue (ModestMailOperation *self,
                                 ModestTnySendQueue *queue)
@@ -3152,6 +3153,42 @@ modest_mail_operation_run_queue (ModestMailOperation *self,
 }
 
 static void
+shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
+{
+       ModestMailOperation *self = (ModestMailOperation *) userdata;
+       ModestMailOperationPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
+       g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+
+       priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+
+       modest_mail_operation_notify_end (self);
+       g_object_unref (self);
+}
+
+void
+modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
+{
+       ModestMailOperationPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
+       g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+
+       modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
+
+       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
+       priv->account = NULL;
+       priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
+
+       modest_mail_operation_notify_start (self);
+       g_object_ref (self);
+       modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
+}
+
+static void
 sync_folder_finish_callback (TnyFolder *self, 
                             gboolean cancelled, 
                             GError *err, 
index 7c43ac0..9017847 100644 (file)
@@ -34,6 +34,7 @@
 #include <tny-folder-store.h>
 #include <widgets/modest-msg-edit-window.h>
 #include <modest-tny-send-queue.h>
+#include <modest-tny-account-store.h>
 
 G_BEGIN_DECLS
 
@@ -76,6 +77,7 @@ typedef enum {
        MODEST_MAIL_OPERATION_TYPE_INFO,
        MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE,
        MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER,
+       MODEST_MAIL_OPERATION_TYPE_SHUTDOWN,
        MODEST_MAIL_OPERATION_TYPE_UNKNOWN,
 } ModestMailOperationTypeOperation;
 
@@ -647,6 +649,16 @@ void          modest_mail_operation_run_queue       (ModestMailOperation *self,
 void          modest_mail_operation_sync_folder     (ModestMailOperation *self,
                                                     TnyFolder *folder, gboolean expunge);
 
+/**
+ * modest_mail_operation_shutdown:
+ * @self: a #ModestMailOperation
+ * @account_store: a #ModestTnyAccountStore
+ *
+ * disconnects all accounts in the account store (doing the proper syncs).
+ */
+void          modest_mail_operation_shutdown        (ModestMailOperation *self,
+                                                    ModestTnyAccountStore *account_store);
+
 /* Functions to control mail operations */
 /**
  * modest_mail_operation_get_task_done:
index b330ca2..3214858 100644 (file)
@@ -46,23 +46,35 @@ static gboolean
 on_idle_exit_modest (gpointer data)
 {
        MainSignalHandlers *handlers;
+       ModestMailOperationQueue *mail_op_queue;
 
        /* Protect the Gtk calls */
        gdk_threads_enter ();
-
-       /* Disconnect signals. Will be freed by the destroy notify */
-       handlers = (MainSignalHandlers *) data;
-       g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (), 
-                                    handlers->queue_handler);
-       g_signal_handler_disconnect (modest_runtime_get_window_mgr (), 
-                                    handlers->window_list_handler);
-
-       /* Wait for remaining tasks */
-       while (gtk_events_pending ())
-               gtk_main_iteration ();
-
-       gtk_main_quit ();
-
+       mail_op_queue = modest_runtime_get_mail_operation_queue ();
+
+       if (modest_mail_operation_queue_running_shutdown (mail_op_queue)) {
+
+               /* Disconnect signals. Will be freed by the destroy notify */
+               handlers = (MainSignalHandlers *) data;
+               g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (), 
+                                            handlers->queue_handler);
+               g_signal_handler_disconnect (modest_runtime_get_window_mgr (), 
+                                            handlers->window_list_handler);
+               /* Wait for remaining tasks */
+               while (gtk_events_pending ())
+                       gtk_main_iteration ();
+               
+               g_free (handlers);
+               
+               gtk_main_quit ();
+       } else {
+               ModestMailOperation *mail_op;
+               mail_op = modest_mail_operation_new (NULL);
+               modest_mail_operation_queue_add (mail_op_queue, mail_op);
+               modest_mail_operation_shutdown (mail_op, modest_runtime_get_account_store ());
+               g_object_unref (mail_op);
+       }
+               
        gdk_threads_leave ();
 
        return FALSE;
@@ -78,7 +90,7 @@ on_queue_empty (ModestMailOperationQueue *queue,
           windows. We can exit as well if the main window is hidden
           and it's the only one */
        if (modest_window_mgr_num_windows (mgr) == 0)
-               g_idle_add_full (G_PRIORITY_LOW, on_idle_exit_modest, user_data, g_free);
+               g_idle_add_full (G_PRIORITY_LOW, on_idle_exit_modest, user_data, NULL);
 }
 
 static void
@@ -89,7 +101,7 @@ on_window_list_empty (ModestWindowMgr *window_mgr,
 
        /* Exit if there are no more windows and the queue is empty */
        if (modest_mail_operation_queue_num_elements (queue) == 0)
-               g_idle_add_full (G_PRIORITY_LOW, on_idle_exit_modest, user_data, g_free);
+               g_idle_add_full (G_PRIORITY_LOW, on_idle_exit_modest, user_data, NULL);
 }
 
 int
index f086183..f26d516 100644 (file)
@@ -301,20 +301,6 @@ modest_tny_account_store_instance_init (ModestTnyAccountStore *obj)
 
 /* disconnect the list of TnyAccounts */
 static void
-account_disconnect (TnyAccount *account)
-{
-       g_return_if_fail (account && TNY_IS_ACCOUNT(account));
-
-       if (TNY_IS_STORE_ACCOUNT (account) && 
-           !modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
-               return;
-
-       tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(account), FALSE, NULL, NULL);
-}
-
-
-/* disconnect the list of TnyAccounts */
-static void
 account_verify_last_ref (TnyAccount *account, const gchar *str)
 {
        gchar *txt;
@@ -838,14 +824,12 @@ modest_tny_account_store_finalize (GObject *obj)
 
        /* Destroy all accounts. Disconnect all accounts before they are destroyed */
        if (priv->store_accounts) {
-               tny_list_foreach (priv->store_accounts, (GFunc)account_disconnect, NULL);
                tny_list_foreach (priv->store_accounts, (GFunc)account_verify_last_ref, "store");
                g_object_unref (priv->store_accounts);
                priv->store_accounts = NULL;
        }
        
        if (priv->transport_accounts) {
-               tny_list_foreach (priv->transport_accounts, (GFunc)account_disconnect, NULL);
                tny_list_foreach (priv->transport_accounts, (GFunc)account_verify_last_ref, "transport");
                g_object_unref (priv->transport_accounts);
                priv->transport_accounts = NULL;
@@ -2188,3 +2172,67 @@ modest_tny_account_store_show_account_settings_dialog (ModestTnyAccountStore *se
        }
        
 }
+
+typedef struct {
+       ModestTnyAccountStore *account_store;
+       ModestTnyAccountStoreShutdownCallback callback;
+       gpointer userdata;
+       gint pending;
+} ShutdownOpData;
+
+static void
+account_shutdown_callback (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer userdata)
+{
+       ShutdownOpData *op_data = (ShutdownOpData *) userdata;
+       op_data->pending--;
+       if (op_data->pending == 0) {
+               if (op_data->callback)
+                       op_data->callback (op_data->account_store, op_data->userdata);
+               g_object_unref (op_data->account_store);
+               g_free (op_data);
+       }
+}
+
+static void
+account_shutdown (TnyAccount *account, ShutdownOpData *op_data)
+{
+       g_return_if_fail (account && TNY_IS_ACCOUNT(account));
+
+       if (TNY_IS_STORE_ACCOUNT (account) && 
+           !modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
+               return;
+
+       op_data->pending++;
+
+       tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(account), FALSE, account_shutdown_callback, op_data);
+}
+
+
+void 
+modest_tny_account_store_shutdown (ModestTnyAccountStore *self,
+                                  ModestTnyAccountStoreShutdownCallback callback,
+                                  gpointer userdata)
+{
+       ShutdownOpData *op_data = g_new0 (ShutdownOpData, 1);
+       ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self);
+       op_data->callback = callback;
+       op_data->userdata = userdata;
+       op_data->pending = 0;
+       op_data->account_store = g_object_ref (self);
+       
+       /* Destroy all accounts. Disconnect all accounts before they are destroyed */
+       if (priv->store_accounts) {
+               tny_list_foreach (priv->store_accounts, (GFunc)account_shutdown, op_data);
+       }
+       
+       if (priv->transport_accounts) {
+               tny_list_foreach (priv->transport_accounts, (GFunc)account_shutdown, op_data);
+       }
+
+       if (op_data->pending == 0) {
+               if (op_data->callback)
+                       op_data->callback (op_data->account_store, op_data->userdata);
+               g_object_unref (op_data->account_store);
+               g_free (op_data);
+       }
+}
index 1ed6d50..ccdb108 100644 (file)
@@ -247,6 +247,21 @@ TnyTransportAccount * modest_tny_account_store_new_connection_specific_transport
 GtkWidget *modest_tny_account_store_show_account_settings_dialog (ModestTnyAccountStore *self,
                                                                  const gchar *account_name);
 
+typedef void (*ModestTnyAccountStoreShutdownCallback) (ModestTnyAccountStore *account_store, gpointer userdata);
+
+/**
+ * modest_tny_account_store_shutdown:
+ * @self: a #ModestTnyAccountStore
+ * @callback: a #ModestTnyAccountStoreShutdownCallback
+ * @userdata: a #gpointer
+ *
+ * Disconnects all registered accounts (forcing syncs for all of them).
+ */
+void modest_tny_account_store_shutdown (ModestTnyAccountStore *self,
+                                       ModestTnyAccountStoreShutdownCallback callback,
+                                       gpointer userdata);
+                                       
+
 G_END_DECLS
 
 #endif /* __MODEST_TNY_ACCOUNT_STORE_H__ */