From 99f716aa0647980dad4b076cf4f5bb7f1debc1a1 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 31 Mar 2008 09:39:48 +0000 Subject: In call_sync, on stale cache errors due to a mount daemon disappearing, 2008-03-31 Alexander Larsson * client/gvfsdaemondbus.[ch]: In call_sync, on stale cache errors due to a mount daemon disappearing, invalidate caches and return G_VFS_ERROR_RETRY so that the caller can retry with fresh caches. * client/gdaemonfile.c: Retry calls on G_VFS_ERROR_RETRY. svn path=/branches/gnome-2-22/; revision=1705 --- ChangeLog | 11 ++++++ client/gdaemonfile.c | 51 ++++++++++++++++++++++++--- client/gvfsdaemondbus.c | 91 ++++++++++++++++++++++++++++++++++++++----------- client/gvfsdaemondbus.h | 10 ++++++ 4 files changed, 139 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 949858e3..22150b6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-03-31 Alexander Larsson + + * client/gvfsdaemondbus.[ch]: + In call_sync, on stale cache errors due to a + mount daemon disappearing, invalidate caches and + return G_VFS_ERROR_RETRY so that the caller can + retry with fresh caches. + + * client/gdaemonfile.c: + Retry calls on G_VFS_ERROR_RETRY. + 2008-03-28 Benjamin Otte * daemon/gvfsbackendftp.c: (ftp_connection_pop_job): diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c index 43e09e38..a191b4ce 100644 --- a/client/gdaemonfile.c +++ b/client/gdaemonfile.c @@ -398,7 +398,10 @@ do_sync_path_call (GFile *file, { DBusMessage *message, *reply; va_list var_args; + GError *my_error; + retry: + message = create_empty_message (file, op, mount_info_out, error); if (!message) return NULL; @@ -409,12 +412,24 @@ do_sync_path_call (GFile *file, var_args); va_end (var_args); + + my_error = NULL; reply = _g_vfs_daemon_call_sync (message, connection_out, NULL, NULL, NULL, - cancellable, error); + cancellable, &my_error); dbus_message_unref (message); + if (reply == NULL) + { + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_error_free (my_error); + goto retry; + } + g_propagate_error (error, my_error); + } + return reply; } @@ -437,7 +452,10 @@ do_sync_2_path_call (GFile *file1, GMountInfo *mount_info1, *mount_info2; const char *path1, *path2; va_list var_args; + GError *my_error; + retry: + mount_info1 = _g_daemon_vfs_get_mount_info_sync (daemon_file1->mount_spec, daemon_file1->path, error); @@ -488,18 +506,29 @@ do_sync_2_path_call (GFile *file1, first_arg_type, var_args); va_end (var_args); - + + my_error = NULL; reply = _g_vfs_daemon_call_sync (message, connection_out, callback_obj_path, callback, callback_user_data, - cancellable, error); + cancellable, &my_error); dbus_message_unref (message); g_mount_info_unref (mount_info1); if (mount_info2) g_mount_info_unref (mount_info2); + + if (reply == NULL) + { + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_error_free (my_error); + goto retry; + } + g_propagate_error (error, my_error); + } return reply; } @@ -1840,7 +1869,10 @@ g_daemon_file_set_attribute (GFile *file, DBusMessage *message, *reply; DBusMessageIter iter; dbus_uint32_t flags_dbus; + GError *my_error; + retry: + message = create_empty_message (file, G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE, NULL, error); if (!message) return FALSE; @@ -1854,13 +1886,22 @@ g_daemon_file_set_attribute (GFile *file, _g_dbus_append_file_attribute (&iter, attribute, type, value_p); + my_error = NULL; reply = _g_vfs_daemon_call_sync (message, NULL, NULL, NULL, NULL, - cancellable, error); + cancellable, &my_error); if (reply == NULL) - return FALSE; + { + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_error_free (my_error); + goto retry; + } + g_propagate_error (error, my_error); + return FALSE; + } dbus_message_unref (reply); return TRUE; diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c index 4a2cb45f..c062cbdc 100644 --- a/client/gvfsdaemondbus.c +++ b/client/gvfsdaemondbus.c @@ -65,6 +65,15 @@ static GHashTable *obj_path_map = NULL; G_LOCK_DEFINE_STATIC(obj_path_map); static void setup_async_fd_receive (VfsConnectionData *connection_data); +static void invalidate_local_connection (const char *dbus_id, + GError **error); + + +GQuark +_g_vfs_error_quark (void) +{ + return g_quark_from_static_string ("g-vfs-error-quark"); +} static gpointer vfs_dbus_init (gpointer arg) @@ -690,9 +699,6 @@ _g_vfs_daemon_call_sync (DBusMessage *message, if (connection == NULL) return NULL; - /* TODO: Handle errors below due to unmount and invalidate the - sync connection cache */ - if (g_cancellable_set_error_if_cancelled (cancellable, error)) return NULL; @@ -715,11 +721,12 @@ _g_vfs_daemon_call_sync (DBusMessage *message, G_VFS_DBUS_TIMEOUT_MSECS)) _g_dbus_oom (); - if (pending == NULL) + if (pending == NULL || + !dbus_connection_get_is_connected (connection)) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error while getting peer-to-peer dbus connection: %s", - "Connection is closed"); + if (pending) + dbus_pending_call_unref (pending); + invalidate_local_connection (dbus_id, error); goto out; } @@ -804,7 +811,17 @@ _g_vfs_daemon_call_sync (DBusMessage *message, &derror); if (!reply) { - _g_error_from_dbus (&derror, error); + if (dbus_error_has_name (&derror, DBUS_ERROR_NO_REPLY) && + !dbus_connection_get_is_connected (connection)) + { + /* The mount for this connection died, we invalidate + * the caches, and then caller needs to retry. + */ + + invalidate_local_connection (dbus_id, error); + } + else + _g_error_from_dbus (&derror, error); dbus_error_free (&derror); goto out; } @@ -852,6 +869,24 @@ free_local_connections (ThreadLocalConnections *local) g_free (local); } +static void +invalidate_local_connection (const char *dbus_id, + GError **error) +{ + ThreadLocalConnections *local; + + _g_daemon_vfs_invalidate_dbus_id (dbus_id); + + local = g_static_private_get (&local_connections); + if (local) + g_hash_table_remove (local->connections, dbus_id); + + g_set_error (error, + G_VFS_ERROR, + G_VFS_ERROR_RETRY, + "Cache invalid, retry (internally handled)"); +} + DBusConnection * _g_dbus_connection_get_sync (const char *dbus_id, GError **error) @@ -877,20 +912,38 @@ _g_dbus_connection_get_sync (const char *dbus_id, } if (dbus_id == NULL) - connection = local->session_bus; + { + /* Session bus */ + + if (local->session_bus) + { + if (dbus_connection_get_is_connected (local->session_bus)) + return local->session_bus; + + /* Session bus was disconnected, re-connect */ + local->session_bus = NULL; + dbus_connection_unref (local->session_bus); + } + } else - connection = g_hash_table_lookup (local->connections, dbus_id); - - if (connection != NULL) { - if (!dbus_connection_get_is_connected (connection)) + /* Mount daemon connection */ + + connection = g_hash_table_lookup (local->connections, dbus_id); + if (connection != NULL) { - _g_daemon_vfs_invalidate_dbus_id (dbus_id); - g_hash_table_remove (local->connections, dbus_id); - return NULL; + if (!dbus_connection_get_is_connected (connection)) + { + /* The mount for this connection died, we invalidate + * the caches, and then caller needs to retry. + */ + + invalidate_local_connection (dbus_id, error); + return NULL; + } + + return connection; } - else - return connection; } dbus_error_init (&derror); @@ -910,7 +963,7 @@ _g_dbus_connection_get_sync (const char *dbus_id, local->session_bus = bus; if (dbus_id == NULL) - return bus; + return bus; /* We actually wanted the session bus, so done */ } message = dbus_message_new_method_call (dbus_id, diff --git a/client/gvfsdaemondbus.h b/client/gvfsdaemondbus.h index 46874f7e..7a132cdc 100644 --- a/client/gvfsdaemondbus.h +++ b/client/gvfsdaemondbus.h @@ -29,6 +29,16 @@ G_BEGIN_DECLS +/* Used for internal errors */ +GQuark _g_vfs_error_quark (void); +#define G_VFS_ERROR _g_vfs_error_quark() + +typedef enum +{ + G_VFS_ERROR_RETRY +} GVfsError; + + typedef void (*GVfsAsyncDBusCallback) (DBusMessage *reply, DBusConnection *connection, GError *io_error, -- cgit v1.2.1