From 08380ae64ec3d29f1335ce1d1a4a7b601be7903d Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Wed, 5 Dec 2007 15:11:26 +0000 Subject: ** Add basic support for crash recovery 2007-12-05 Srinivasa Ragavan ** Add basic support for crash recovery * apps_evolution_shell.schemas.in: Keys to recover and recovery dialog. * e-shell.c: (e_shell_quit): Delete the lock while quitting. * main.c: (show_recovery_warning), (idle_cb): Create lock and also show the warning dialog. svn path=/trunk/; revision=34652 --- e-util/ChangeLog | 7 +++ e-util/e-util.c | 49 +++++++++++++++++ e-util/e-util.h | 4 ++ shell/ChangeLog | 9 +++ shell/apps_evolution_shell.schemas.in | 27 ++++++++- shell/e-shell.c | 3 + shell/main.c | 100 +++++++++++++++++++++++++++++++++- 7 files changed, 197 insertions(+), 2 deletions(-) diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 06a841a3d7..1cd661efc8 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,10 @@ +2007-12-05 Srinivasa Ragavan + + * e-util.c: (get_lock_filename), (e_file_lock_create), + (e_file_lock_destroy), (e_file_lock_exists): Add utility functions for + startup-running lock create, check and delete. + * e-util.h: + 2007-12-04 Milan Crha ** Part of fix for bug #500210 diff --git a/e-util/e-util.c b/e-util/e-util.c index 625c617a8b..b1634bcfff 100644 --- a/e-util/e-util.c +++ b/e-util/e-util.c @@ -1017,3 +1017,52 @@ e_file_get_save_path (void) return (uri); } +/* Evolution Locks for crash recovery */ + +#define LOCK_FILE ".running" + +static const gchar * +get_lock_filename (void) +{ + static gchar *filename = NULL; + + if (G_UNLIKELY (filename == NULL)) + filename = g_build_filename (g_get_home_dir (), ".evolution", LOCK_FILE, NULL); + + return filename; +} + +gboolean +e_file_lock_create () +{ + const char *fname = get_lock_filename (); + gboolean status = FALSE; + + int fd = g_creat (fname, S_IRUSR|S_IWUSR); + if (fd == -1){ + g_warning ("Lock file '%s' creation failed, error %d\n", fname, errno); + } else { + status = TRUE; + close (fd); + } + + return status; +} + +void +e_file_lock_destroy () +{ + const char *fname = get_lock_filename (); + + if (g_unlink (fname) == -1){ + g_warning ("Lock destroy: failed to unlink file '%s'!",fname); + } +} + +gboolean +e_file_lock_exists () +{ + const char *fname = get_lock_filename (); + + return g_file_test (fname, G_FILE_TEST_EXISTS); +} diff --git a/e-util/e-util.h b/e-util/e-util.h index e3774c5852..b37f2abdb5 100644 --- a/e-util/e-util.h +++ b/e-util/e-util.h @@ -111,6 +111,10 @@ void e_file_update_save_path (gchar *uri, gboolean free); gchar * e_file_get_save_path (void); +gboolean e_file_lock_create (); +void e_file_lock_destroy (); +gboolean e_file_lock_exists (); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/shell/ChangeLog b/shell/ChangeLog index 2e97d88040..3e5f090d0c 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,3 +1,12 @@ +2007-12-05 Srinivasa Ragavan + + ** Add basic support for crash recovery + + * apps_evolution_shell.schemas.in: Keys to recover and recovery dialog. + * e-shell.c: (e_shell_quit): Delete the lock while quitting. + * main.c: (show_recovery_warning), (idle_cb): Create lock and also show + the warning dialog. + 2007-11-30 Matthew Barnes ** Fixes bug #499920 diff --git a/shell/apps_evolution_shell.schemas.in b/shell/apps_evolution_shell.schemas.in index f7d1e71f98..5375f09845 100644 --- a/shell/apps_evolution_shell.schemas.in +++ b/shell/apps_evolution_shell.schemas.in @@ -41,7 +41,32 @@ - + + + /schemas/apps/evolution/shell/skip_recovery_dialog + /apps/evolution/shell/skip_recovery_dialog + evolution + bool + false + + Skip recovery warning dialog + Whether the warning dialog in recovery of Evolution is skipped. + + + + + /schemas/apps/evolution/shell/recovery + /apps/evolution/shell/recovery + evolution + bool + true + + Whether crash recovery should be done or not + Decides whether the crash recovery should be run or not + + + + /schemas/apps/evolution/shell/start_offline diff --git a/shell/e-shell.c b/shell/e-shell.c index 4e651453a4..51ab69c8c1 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -1377,6 +1377,9 @@ e_shell_quit(EShell *shell) e_shell_window_save_defaults (p->data); } can_quit = !es_run_quit(shell); + + /* Mark a safe quit by destroying the lock. */ + e_file_lock_destroy (); } return can_quit; diff --git a/shell/main.c b/shell/main.c index 4d9e785cc3..bcd7fbada4 100644 --- a/shell/main.c +++ b/shell/main.c @@ -31,6 +31,7 @@ #include #include "e-shell-constants.h" #include "e-util/e-profile-event.h" +#include "e-util/e-util.h" #include "e-shell.h" #include "es-menu.h" @@ -91,6 +92,11 @@ #define SKIP_WARNING_DIALOG_KEY \ "/apps/evolution/shell/skip_warning_dialog" +#define SKIP_RECOVERY_DIALOG_KEY \ + "/apps/evolution/shell/skip_recovery_dialog" +#define RECOVERY_KEY \ + "/apps/evolution/shell/recovery" + static EShell *shell = NULL; @@ -284,6 +290,70 @@ destroy_config (GConfClient *client) #endif /* DEVELOPMENT */ +static int +show_recovery_warning(void) +{ + GtkWidget *vbox; + GtkWidget *label; + GtkWidget *warning_dialog; + GtkWidget *checkbox; + GtkWidget *alignment; + gboolean skip; + char *text; + int flags = 0, response; + + warning_dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (warning_dialog), _("Evolution Crash Recovery")); + gtk_window_set_modal (GTK_WINDOW (warning_dialog), TRUE); + gtk_dialog_add_button (GTK_DIALOG (warning_dialog), _("Ig_nore"), GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (warning_dialog), _("_Recover"), GTK_RESPONSE_OK); + + gtk_dialog_set_has_separator (GTK_DIALOG (warning_dialog), FALSE); + + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (warning_dialog)->vbox), 0); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (warning_dialog)->action_area), 12); + + vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (warning_dialog)->vbox), vbox, + TRUE, TRUE, 0); + + text = g_strdup( + /* xgettext:no-c-format */ + _("Evolution appears to have exited unexpectedly the last time it was\n" + "run. As a precautionary measure, all preview panes will be hidden.\n" + "You can restore the preview panes from the View menu.\n")); + label = gtk_label_new (text); + g_free(text); + + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0); + + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); + + checkbox = gtk_check_button_new_with_mnemonic (_("_Do not show this again")); + + alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + + gtk_container_add (GTK_CONTAINER (alignment), checkbox); + gtk_box_pack_start (GTK_BOX (vbox), alignment, TRUE, TRUE, 0); + + gtk_widget_show_all (warning_dialog); + + response = gtk_dialog_run (GTK_DIALOG (warning_dialog)); + + if (response != GTK_RESPONSE_CANCEL) + flags = flags|(1<<1); + + skip = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)); + if (skip) + flags = flags|(1<<2); + + gtk_widget_destroy (warning_dialog); + + return flags; +} + static void open_uris (GNOME_Evolution_Shell corba_shell, gchar **uris) { @@ -363,8 +433,36 @@ idle_cb (gchar **uris) if (shell != NULL) { if (uris != NULL) open_uris (corba_shell, uris); - else + else { + GConfClient *client = gconf_client_get_default (); + + if (gconf_client_get_bool (client, RECOVERY_KEY, NULL) && e_file_lock_exists ()) { + /* It should have crashed last time or a force-shutdown */ + gboolean skip = gconf_client_get_bool (client, SKIP_RECOVERY_DIALOG_KEY, NULL); + gboolean recover = TRUE; + if (!skip){ + int flags = show_recovery_warning (); + + gconf_client_set_bool (client, SKIP_RECOVERY_DIALOG_KEY, (flags & (1<<2)) ? TRUE : FALSE, NULL); + recover = (flags & (1<<1)) ? TRUE: FALSE; + } + + if (recover) { + /* Disable the previews */ + gconf_client_set_bool (client, "/apps/evolution/mail/display/show_preview", FALSE, NULL); + gconf_client_set_bool (client, "/apps/evolution/mail/display/safe_list", TRUE, NULL); + gconf_client_set_bool (client, "/apps/evolution/addressbook/display/show_preview", FALSE, NULL); + gconf_client_set_bool (client, "/apps/evolution/calendar/display/show_task_preview", FALSE, NULL); + } + /* Let us not delete and recreate a lock, instead reuse it. We don't use timestamps anyways */ + } else { + /* What great can we do, if lock creation fails ?*/ + e_file_lock_create (); + } + g_object_unref (client); + e_shell_create_window (shell, default_component_id, NULL); + } } else { CORBA_Environment ev; -- cgit v1.2.3