From 2bee1bbbdfc12986d839c7be9a72da4bca47b0ad Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 22 Nov 2011 10:02:49 -0500 Subject: [PATCH] core: A bit more daemon work --- Makefile-daemon.am | 2 +- src/daemon/{main.c => ostreed.c} | 0 src/daemon/ot-daemon.c | 170 +++++++++++++++++++++++++++++-- src/daemon/ot-daemon.h | 17 ++++ 4 files changed, 178 insertions(+), 11 deletions(-) rename src/daemon/{main.c => ostreed.c} (100%) diff --git a/Makefile-daemon.am b/Makefile-daemon.am index 898e2f9c..c1d21e98 100644 --- a/Makefile-daemon.am +++ b/Makefile-daemon.am @@ -19,7 +19,7 @@ libexec_PROGRAMS += ostreed -ostreed_SOURCES = src/daemon/main.c \ +ostreed_SOURCES = src/daemon/ostreed.c \ src/daemon/ot-daemon.h \ src/daemon/ot-daemon.c \ $(NULL) diff --git a/src/daemon/main.c b/src/daemon/ostreed.c similarity index 100% rename from src/daemon/main.c rename to src/daemon/ostreed.c diff --git a/src/daemon/ot-daemon.c b/src/daemon/ot-daemon.c index cb3e275a..d7793b79 100644 --- a/src/daemon/ot-daemon.c +++ b/src/daemon/ot-daemon.c @@ -51,12 +51,143 @@ static const gchar introspection_xml[] = " " " " " " - " " - " " + " " + " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " ""; + +static void +operation_new (OstreeDaemon *self, + const char *sender, + guint *out_id, + OstreeDaemonOperation **out_op) +{ + + *out_id = ++self->op_id; + *out_op = g_new0 (OstreeDaemonOperation, 1); + (*out_op)->requestor_dbus_name = g_strdup (sender); + (*out_op)->cancellable = g_cancellable_new (); +} + +static void +operation_free (OstreeDaemonOperation *op) +{ + g_free (op->requestor_dbus_name); + g_object_unref (op->cancellable); + g_free (op); +} + +static gboolean +op_return (OstreeDaemon *self, + OstreeDaemonOperation *op, + GError *error_return) +{ + gboolean ret = FALSE; + GVariant *args = NULL; + + g_hash_table_remove (self->ops, GUINT_TO_POINTER (op->id)); + + if (error_return) + args = g_variant_new ("(ubs)", op->id, FALSE, error_return->message); + else + args = g_variant_new ("(ubs)", op->id, TRUE, "Success"); + + g_dbus_connection_emit_signal (self->bus, + op->requestor_dbus_name, + OSTREE_DAEMON_PATH, + OSTREE_DAEMON_IFACE, + "OperationEnded", + args, + NULL); + + ret = TRUE; + operation_free (op); + if (args) + g_variant_unref (args); + return ret; +} + +typedef struct { + OstreeDaemonOperation *op; + GFile *dir; +} OverlayDirThreadData; + +typedef struct { + OverlayDirThreadData *tdata; + GError *error; +} OverlayDirEmitInIdleData; + +static gboolean +overlay_dir_emit_in_idle (gpointer data) +{ + OverlayDirEmitInIdleData *idledata = data; + + op_return (idledata->tdata->op->daemon, + idledata->tdata->op, + idledata->error); + + g_free (idledata); + + return FALSE; +} + +static gpointer +overlay_dir_thread (gpointer data) +{ + OverlayDirThreadData *tdata = data; + GMainContext *context = NULL; + GFile *sysroot_f = NULL; + OverlayDirEmitInIdleData *idledata = g_new0 (OverlayDirEmitInIdleData, 1); + + idledata->tdata = tdata; + + context = g_main_context_new (); + + sysroot_f = ot_gfile_new_for_path ("/sysroot/ostree/current"); + + g_main_context_push_thread_default (context); + + (void)ot_gfile_merge_dirs (sysroot_f, + tdata->dir, + tdata->op->cancellable, + &(idledata->error)); + g_idle_add (overlay_dir_emit_in_idle, idledata); + + g_main_context_pop_thread_default (context); + + g_main_context_unref (context); + + g_clear_object (&tdata->dir); + g_free (tdata); + + return NULL; +} + +static void +do_op_overlay (OstreeDaemon *self, + const char *dir, + OstreeDaemonOperation *op) +{ + OverlayDirThreadData *tdata = g_new0 (OverlayDirThreadData, 1); + + tdata->op = op; + tdata->dir = ot_gfile_new_for_path (dir); + + g_thread_create_full (overlay_dir_thread, tdata, 0, FALSE, FALSE, + G_THREAD_PRIORITY_NORMAL, NULL); +} + static void handle_method_call (GDBusConnection *connection, const gchar *sender, @@ -67,6 +198,23 @@ handle_method_call (GDBusConnection *connection, GDBusMethodInvocation *invocation, gpointer user_data) { + OstreeDaemon *self = user_data; + guint32 op_id; + OstreeDaemonOperation *op; + + if (g_strcmp0 (method_name, "Overlay") == 0) + { + const gchar *dirpath; + + g_variant_get (parameters, "(&s)", &dirpath); + + operation_new (self, sender, &op_id, &op); + + do_op_overlay (self, dirpath, op); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(u)", op_id)); + } } static const GDBusInterfaceVTable interface_vtable = @@ -81,10 +229,13 @@ on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { + OstreeDaemon *self = user_data; guint id; + self->bus = g_object_ref (connection); + id = g_dbus_connection_register_object (connection, - "/org/gnome/OSTree", + OSTREE_DAEMON_PATH, introspection_data->interfaces[0], &interface_vtable, NULL, /* user_data */ @@ -98,11 +249,11 @@ on_name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { - OstreeDaemon *daemon = user_data; + OstreeDaemon *self = user_data; GError *error = NULL; - daemon->repo = ostree_repo_new ("/sysroot/ostree/repo"); - if (!ostree_repo_check (daemon->repo, &error)) + self->repo = ostree_repo_new ("/sysroot/ostree/repo"); + if (!ostree_repo_check (self->repo, &error)) { g_printerr ("%s\n", error->message); g_clear_error (&error); @@ -118,7 +269,6 @@ on_name_lost (GDBusConnection *connection, exit (1); } - OstreeDaemon * ostree_daemon_new (void) { @@ -126,10 +276,8 @@ ostree_daemon_new (void) ret->loop = g_main_loop_new (NULL, TRUE); - introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); - ret->name_id = g_bus_own_name (G_BUS_TYPE_SYSTEM, - "org.gnome.OSTree", + OSTREE_DAEMON_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, on_name_acquired, @@ -137,6 +285,8 @@ ostree_daemon_new (void) NULL, NULL); + ret->ops = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, NULL); + return ret; } diff --git a/src/daemon/ot-daemon.h b/src/daemon/ot-daemon.h index 4077bf1a..b0d87788 100644 --- a/src/daemon/ot-daemon.h +++ b/src/daemon/ot-daemon.h @@ -25,15 +25,32 @@ #include +#define OSTREE_DAEMON_NAME "org.gnome.OSTree" +#define OSTREE_DAEMON_PATH "/org/gnome/OSTree" +#define OSTREE_DAEMON_IFACE "org.gnome.OSTree" + G_BEGIN_DECLS typedef struct { GMainLoop *loop; OstreeRepo *repo; + GDBusConnection *bus; + int name_id; + + guint32 op_id; + + GHashTable *ops; } OstreeDaemon; +typedef struct { + guint32 id; + OstreeDaemon *daemon; + char *requestor_dbus_name; + GCancellable *cancellable; +} OstreeDaemonOperation; + OstreeDaemon *ostree_daemon_new (void); G_END_DECLS