Re: GDBus API Questions; was: GDBus/GVariant plans for next GLib release
- From: Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>
- To: David Zeuthen <david fubar dk>
- Cc: gtk-devel-list gnome org
- Subject: Re: GDBus API Questions; was: GDBus/GVariant plans for next GLib release
- Date: Wed, 28 Oct 2009 21:23:30 +0100
2009/10/28 Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>:
> 2009/10/28 Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>:
>> 2009/10/27 Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>:
>>> 2009/10/27 David Zeuthen <david fubar dk>:
>>>> Hey Mikkel,
>>>>
>>>> On Mon, 2009-10-26 at 23:52 +0100, Mikkel Kamstrup Erlandsen wrote:
>>>>> > I just looked over the newly introduced
>>>>> > g_dbus_connection_register_subtree() and related data structures, and
>>>>> > I think it will fit very nicely with what I am going to need. All in
>>>>> > all it looks really sweet, good work.
>>>>> >
>>>>> > One thing though is that as I read it objects in a subtree must be
>>>>> > known before method calls are accepted to them? For my use case in
>>>>> > Zeitgeist I was hoping that I could completely get rid of a "Manager"
>>>>> > type of interface, and just implicitly create objects in the tree
>>>>> > whenever calls where made to them. This does not look possible as it
>>>>> > stands?
>>>>> >
>>>>> > Maybe allowing '*' as a wildcard node name in the subtree enumeration function?
>>>>
>>>> I'm actually a bit wary of introducing this kind of functionality -
>>>> mainly, I guess, because it screws with the notion that a D-Bus service
>>>> export a set of objects. In particular it makes it hard to
>>>> debug/introspect the service - for example, in extreme abuses of such a
>>>> feature (not the use-case you are suggesting though), you can't really
>>>> use e.g. d-feet to get an idea of what kind of objects are exported and
>>>> known by the service.
>>>>
>>>> The subtree functionality is really just for performance hacks - the
>>>> intended use is to avoid creating a huge amount of objects. For example,
>>>> one use case is export the subtree /org/foo/Project/processes/<pid>
>>>> where <pid> is, say, a UNIX process id. With the subtree handler, no
>>>> object creation over is necessary.
>>>>
>>>> Anyway, your original use case does seem sound and reasonable - it
>>>> reduces overhead insofar that the client saves a round-trip to a
>>>> hypothetical Manager.CreateObject() method that would be needed if we
>>>> didn't have this. It does make it less intuitive insofar that remote
>>>> object creation is this magical thing with automatically appearing
>>>> nodes... but I guess that's fine.
>>>
>>> Not to mention the built in race condition you have if the exported
>>> objects can also be deleted via the manager. All client apps would
>>> have to precede all calls to an object by a Create() message (and it
>>> would still be racy). Anyway, enough about this :-) I think it is
>>> probably a fragment of my REST/web background where such patterns are
>>> more common.
>>>
>>>>> I had a stab at this myself. The wildcard idea seemed like a bad one,
>>>>> so I instead added another gboolean param to
>>>>> g_dbus_connection_register_subtree(), @is_dynamic.
>>>>>
>>>>> If is_dynamic is TRUE then objects need not be in the enumerated list
>>>>> of objects in order to be introspected and dispatched. Pretty simple.
>>>>>
>>>>> No matter the simplicity I still managed to screw up one of the unit
>>>>> tests. I will fix it and add some specific tests for the dynamic case
>>>>> if you give the "go" for this David.
>>>>
>>>> Sounds good to me. I'd prefer a GDBusSubtreeFlags flag enumeration with
>>>> a G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES member instead of
>>>> @is_dynamic. Just for future proofing and all. Maybe it would also be
>>>> nice to pass a "gboolean enumerated" to @introspect and @dispatch that
>>>> indicates whether the node was enumerated (or not).
>>>
>>> That sounds like a better idea. I'll have another stab at this tonight
>>> if the kids allow me :-)
>>
>> They did :-)
>>
>> Attached is a series of patches (0001 should be identical to my
>> previous) implementing what you describe, except adding the gboolean
>> enumerated arg to @introspect and @dispatch. I will get around to
>> that.
>>
>> The failing unit tests I described was really just me b0rking up the
>> linking between some installed gdbus components and my devel version.
>> I have them running now[1] and I added some testing for the dynamic
>> objects as well (see 0003).
>
> Some more tests to go with the other patches attached.
And of course the attachment :-S
--
Cheers,
Mikkel
From 9fe0126b9d74dd260e1d3ef3969afe94f8b92fa9 Mon Sep 17 00:00:00 2001
From: Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>
Date: Wed, 28 Oct 2009 20:01:52 +0100
Subject: [PATCH 4/4] test calls to non-existing objects
Add a test for calls to a non-existing object which is then dynamically
spawned on the server
---
gdbus/tests/export.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/gdbus/tests/export.c b/gdbus/tests/export.c
index be911e2..fabc0c3 100644
--- a/gdbus/tests/export.c
+++ b/gdbus/tests/export.c
@@ -375,6 +375,66 @@ count_interfaces (GDBusConnection *c,
return ret;
}
+static void
+dyna_create_callback (GDBusProxy *proxy,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVariant *result;
+ GError *error;
+
+ error = NULL;
+ result = g_dbus_proxy_invoke_method_finish (proxy,
+ res,
+ &error);
+ g_assert_no_error (error);
+ g_assert (result != NULL);
+ g_variant_unref (result);
+
+ g_main_loop_quit (loop);
+}
+
+/* Dynamically create @object_name under /foo/dyna */
+static void
+dyna_create (GDBusConnection *c,
+ const gchar *object_name)
+{
+ GError *error;
+ GDBusProxy *proxy;
+ gchar *object_path;
+
+ object_path = g_strconcat ("/foo/dyna/", object_name, NULL);
+
+ error = NULL;
+ proxy = g_dbus_proxy_new_sync (c,
+ G_TYPE_DBUS_PROXY,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ g_dbus_connection_get_unique_name (c),
+ object_path,
+ "org.example.Dyna",
+ NULL,
+ &error);
+ g_assert_no_error (error);
+ g_assert (proxy != NULL);
+
+ /* do this async to avoid libdbus-1 deadlocks */
+ g_dbus_proxy_invoke_method (proxy,
+ "DynaCyber",
+ g_variant_new ("()"),
+ -1,
+ NULL,
+ (GAsyncReadyCallback) dyna_create_callback,
+ NULL);
+ g_main_loop_run (loop);
+
+ g_assert_no_error (error);
+
+ g_object_unref (proxy);
+ g_free (object_path);
+
+ return;
+}
typedef struct
{
@@ -861,7 +921,7 @@ test_object_registration (void)
g_strfreev (nodes);
g_assert_cmpint (count_interfaces (c, "/foo/dyna"), ==, 4);
- /* Install three nodes in the dynamic subtree via the backdoor and
+ /* Install three nodes in the dynamic subtree via the dyna_data backdoor and
* assert that they show up correctly in the introspection data */
g_ptr_array_add (dyna_data, "lol");
g_ptr_array_add (dyna_data, "cat");
@@ -876,6 +936,19 @@ test_object_registration (void)
g_assert_cmpint (count_interfaces (c, "/foo/dyna/lol"), ==, 4);
g_assert_cmpint (count_interfaces (c, "/foo/dyna/cat"), ==, 4);
g_assert_cmpint (count_interfaces (c, "/foo/dyna/cheezburger"), ==, 4);
+
+ /* Call a non-existing object path and assert that it has been created */
+ dyna_create (c, "dynamicallycreated");
+ nodes = get_nodes_at (c, "/foo/dyna");
+ g_assert (nodes != NULL);
+ g_assert_cmpint (g_strv_length (nodes), ==, 4);
+ g_assert_cmpstr (nodes[0], ==, "lol");
+ g_assert_cmpstr (nodes[1], ==, "cat");
+ g_assert_cmpstr (nodes[2], ==, "cheezburger");
+ g_assert_cmpstr (nodes[3], ==, "dynamicallycreated");
+ g_strfreev (nodes);
+ g_assert_cmpint (count_interfaces (c, "/foo/dyna/dynamicallycreated"), ==, 4);
+
/* now check that the object hierarachy is properly generated... yes, it's a bit
* perverse that we round-trip to the bus to introspect ourselves ;-)
--
1.6.3.3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]