diff options
author | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 09:23:06 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2007-09-13 09:23:06 +0000 |
commit | 6bf04c8bba1ae0c423952268cbbbdf7fde04f27f (patch) | |
tree | 74a13d9473d20cd4ed8eec6cf4ca346a9a35d9aa /daemon/gvfsjobopenforread.c | |
parent | fc23a9a11cbeb452f3a4d66d848e3e8725333650 (diff) | |
download | gvfs-6bf04c8bba1ae0c423952268cbbbdf7fde04f27f.tar.gz |
More work on daemon scheduling etc
Original git commit by Alexander Larsson <alex@localhost.localdomain> at 1161615951 +0200
svn path=/trunk/; revision=119
Diffstat (limited to 'daemon/gvfsjobopenforread.c')
-rw-r--r-- | daemon/gvfsjobopenforread.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/daemon/gvfsjobopenforread.c b/daemon/gvfsjobopenforread.c new file mode 100644 index 00000000..43fcb7d9 --- /dev/null +++ b/daemon/gvfsjobopenforread.c @@ -0,0 +1,177 @@ +#include <config.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <glib.h> +#include <dbus/dbus.h> +#include <glib/gi18n.h> +#include "gvfsreadhandle.h" +#include "gvfsjobopenforread.h" +#include "gvfsdaemonutils.h" + +G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_TYPE_VFS_JOB); + +static gboolean start (GVfsJob *job); +static void send_reply (GVfsJob *job); + +static void +g_vfs_job_open_for_read_finalize (GObject *object) +{ + GVfsJobOpenForRead *job; + + job = G_VFS_JOB_OPEN_FOR_READ (object); + + if (job->message) + dbus_message_unref (job->message); + + /* TODO: manage backend_handle if not put in readhandle */ + + g_free (job->filename); + + if (G_OBJECT_CLASS (g_vfs_job_open_for_read_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_job_open_for_read_parent_class)->finalize) (object); +} + +static void +g_vfs_job_open_for_read_class_init (GVfsJobOpenForReadClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass); + + gobject_class->finalize = g_vfs_job_open_for_read_finalize; + + job_class->start = start; + job_class->send_reply = send_reply; +} + +static void +g_vfs_job_open_for_read_init (GVfsJobOpenForRead *job) +{ +} + +GVfsJob * +g_vfs_job_open_for_read_new (GVfsDaemon *daemon, + DBusConnection *connection, + DBusMessage *message) +{ + GVfsJobOpenForRead *job; + DBusMessage *reply; + DBusError derror; + int path_len; + const char *path_data; + + dbus_error_init (&derror); + if (!dbus_message_get_args (message, &derror, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &path_data, &path_len, + 0)) + { + reply = dbus_message_new_error (message, + derror.name, + derror.message); + dbus_error_free (&derror); + + dbus_connection_send (connection, reply, NULL); + return NULL; + } + + job = g_object_new (G_TYPE_VFS_JOB_OPEN_FOR_READ, NULL); + + G_VFS_JOB (job)->daemon = daemon; + job->connection = connection; /* TODO: ref? */ + job->message = dbus_message_ref (message); + job->filename = g_strndup (path_data, path_len); + + return G_VFS_JOB (job); +} + +static gboolean +start (GVfsJob *job) +{ + GVfsDaemonBackendClass *class; + GVfsJobOpenForRead *op_job = G_VFS_JOB_OPEN_FOR_READ (job); + + class = G_VFS_DAEMON_BACKEND_GET_CLASS (job->daemon->backend); + + return class->open_for_read (job->daemon->backend, + op_job, + op_job->filename); +} + +void +g_vfs_job_open_for_read_set_handle (GVfsJobOpenForRead *job, + GVfsHandle *handle) +{ + job->backend_handle = handle; +} + +/* Might be called on an i/o thread */ +static DBusMessage * +create_reply (GVfsJob *job, + DBusConnection *connection, + DBusMessage *message) +{ + GVfsJobOpenForRead *open_job = G_VFS_JOB_OPEN_FOR_READ (job); + GVfsReadHandle *handle; + DBusMessage *reply; + GError *error; + int fd_id; + gboolean res; + + g_assert (open_job->backend_handle != NULL); + + error = NULL; + handle = g_vfs_read_handle_new (&error); + if (handle == NULL) + { + reply = dbus_message_new_error_from_gerror (message, error); + g_error_free (error); + return reply; + } + + if (!dbus_connection_send_fd (connection, + g_vfs_read_handle_get_remote_fd (handle), + &fd_id, &error)) + { + reply = dbus_message_new_error_from_gerror (message, error); + g_error_free (error); + g_object_unref (handle); + return reply; + } + + reply = dbus_message_new_method_return (message); + res = dbus_message_append_args (reply, + DBUS_TYPE_UINT32, &fd_id, + DBUS_TYPE_INVALID); + + g_vfs_read_handle_close_remote_fd (handle); + g_vfs_read_handle_set_data (handle, open_job->backend_handle); + g_vfs_daemon_register_read_handle (job->daemon, handle); + open_job->backend_handle = NULL; + + return reply; +} + +/* Might be called on an i/o thread */ +static void +send_reply (GVfsJob *job) +{ + GVfsJobOpenForRead *open_job = G_VFS_JOB_OPEN_FOR_READ (job); + DBusMessage *reply; + + if (job->failed) + reply = dbus_message_new_error_from_gerror (open_job->message, job->error); + else + reply = create_reply (job, open_job->connection, open_job->message); + + g_assert (reply != NULL); + + /* Queues reply (threadsafely), actually sends it in mainloop */ + dbus_connection_send (open_job->connection, reply, NULL); + dbus_message_unref (reply); + + g_vfs_job_emit_finished (job); +} |