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: Mon, 26 Oct 2009 23:52:35 +0100
2009/10/25 Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>:
> 2009/10/15 David Zeuthen <david fubar dk>:
>> Hey Mikkel,
>>
>> On Thu, 2009-10-15 at 08:24 +0200, Mikkel Kamstrup Erlandsen wrote:
>>> * Can I register a GDBusInterfaceVTable without registering an
>>> object? The use case I have in mind is something akin to dynamically
>>> spawning objects on the server side when messages are send to objects
>>> under a given path[1]. Fx. when messages are send to
>>> /org/example/item/* I create the item matching * dynamically. Ideally
>>> one would register the vtable for objects matching a regexp. This
>>> would facilitate RESTful message passing on the bus.
>>
>> Yeah, there's a TODO in gdbusconnection.h to say we need something like
>> that - it would be similar dbus_connection_register_fallback() [1]. We
>> probably want a separate GDBusHierarchyVTable with functions to a) list
>> objects in the "directory"; and b) get introspection data for objects in
>> the "directory".
>
> 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 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.
--
Cheers,
Mikkel
PS: And thanks for nice readable and commented code David!
diff --git a/gdbus/example-subtree.c b/gdbus/example-subtree.c
index 041a8f4..f870589 100644
--- a/gdbus/example-subtree.c
+++ b/gdbus/example-subtree.c
@@ -332,6 +332,7 @@ on_name_acquired (GDBusConnection *connection,
registration_id = g_dbus_connection_register_subtree (connection,
"/org/gtk/GDBus/TestSubtree/Devices",
&subtree_vtable,
+ FALSE, /* is_dynamic */
NULL, /* user_data */
NULL, /* user_data_free_func */
NULL); /* GError** */
diff --git a/gdbus/gdbusconnection.c b/gdbus/gdbusconnection.c
index aa21213..d9099c0 100644
--- a/gdbus/gdbusconnection.c
+++ b/gdbus/gdbusconnection.c
@@ -3620,6 +3620,7 @@ struct ExportedSubtree
gchar *object_path;
GDBusConnection *connection;
const GDBusSubtreeVTable *vtable;
+ gboolean is_dynamic;
GMainContext *context;
gpointer user_data;
@@ -3685,6 +3686,8 @@ handle_subtree_introspect (DBusConnection *connection,
//g_debug ("in handle_subtree_introspect for %s", requested_object_path);
+ /* Strictly we don't need the children in dynamic mode, but we avoid the
+ * conditionals to preserve code clarity */
children = es->vtable->enumerate (es->connection,
es->user_data,
sender,
@@ -3693,8 +3696,9 @@ handle_subtree_introspect (DBusConnection *connection,
if (!is_root)
{
requested_node = strrchr (requested_object_path, '/') + 1;
- /* skip if requested node is not part of children */
- if (!_g_strv_has_string ((const gchar * const *) children, requested_node))
+
+ /* Assert existence of object if we are not dynamic */
+ if (!es->is_dynamic && !_g_strv_has_string ((const gchar * const *) children, requested_node))
goto out;
}
else
@@ -3825,8 +3829,9 @@ handle_subtree_method_invocation (DBusConnection *connection,
if (!is_root)
{
requested_node = strrchr (requested_object_path, '/') + 1;
- /* skip if requested node is not part of children */
- if (!_g_strv_has_string ((const gchar * const *) children, requested_node))
+
+ /* If not dynamic, skip if requested node is not part of children */
+ if (!es->is_dynamic && !_g_strv_has_string ((const gchar * const *) children, requested_node))
goto out;
}
else
@@ -4048,6 +4053,9 @@ static const DBusObjectPathVTable dbus_1_subtree_vtable =
* @connection: A #GDBusConnection.
* @object_path: The object path to register the subtree at.
* @vtable: A #GDBusSubtreeVTable to enumerate, introspect and dispatch nodes in the subtree.
+ * @is_dynamic: If %TRUE method calls to objects not in the enumerated range
+ * will still be dispatched. This is useful if you want to
+ * dynamically spawn objects in the subtree.
* @user_data: Data to pass to functions in @vtable.
* @user_data_free_func: Function to call when the subtree is unregistered.
* @error: Return location for error or %NULL.
@@ -4059,8 +4067,9 @@ static const DBusObjectPathVTable dbus_1_subtree_vtable =
* by @object_path.
*
* When handling remote calls into any node in the subtree, first the
- * @enumerate and @introspection function is used to check if the node
- * exists and whether it supports the requested method. If so, the
+ * @enumerate function is used to check if the node exists. If the node exists
+ * or @is_dynamic is set to %TRUE the @introspection function is used to
+ * check if the node supports the requested method. If so, the
* @dispatch function is used to determine where to dispatch the
* call. The collected #GDBusInterfaceVTable and #gpointer will be
* used to call into the interface vtable for processing the request.
@@ -4087,6 +4096,7 @@ guint
g_dbus_connection_register_subtree (GDBusConnection *connection,
const gchar *object_path,
const GDBusSubtreeVTable *vtable,
+ gboolean is_dynamic,
gpointer user_data,
GDestroyNotify user_data_free_func,
GError **error)
@@ -4099,6 +4109,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection,
g_return_val_if_fail (!g_dbus_connection_get_is_disconnected (connection), 0);
g_return_val_if_fail (object_path != NULL, 0);
g_return_val_if_fail (vtable != NULL, 0);
+ g_return_val_if_fail (error == NULL || *error == NULL, 0);
ret = 0;
@@ -4146,6 +4157,7 @@ g_dbus_connection_register_subtree (GDBusConnection *connection,
}
es->vtable = vtable;
+ es->is_dynamic = is_dynamic;
es->id = _global_subtree_registration_id++; /* TODO: overflow etc. */
es->user_data = user_data;
es->user_data_free_func = user_data_free_func;
diff --git a/gdbus/gdbusconnection.h b/gdbus/gdbusconnection.h
index da07e14..cd49a07 100644
--- a/gdbus/gdbusconnection.h
+++ b/gdbus/gdbusconnection.h
@@ -318,6 +318,7 @@ struct _GDBusSubtreeVTable
guint g_dbus_connection_register_subtree (GDBusConnection *connection,
const gchar *object_path,
const GDBusSubtreeVTable *vtable,
+ gboolean is_dynamic,
gpointer user_data,
GDestroyNotify user_data_free_func,
GError **error);
diff --git a/gdbus/tests/export.c b/gdbus/tests/export.c
index 5a678e1..f868d54 100644
--- a/gdbus/tests/export.c
+++ b/gdbus/tests/export.c
@@ -649,6 +649,7 @@ test_object_registration (void)
subtree_registration_id = g_dbus_connection_register_subtree (c,
"/foo/boss/executives",
&subtree_vtable,
+ FALSE,
&data,
on_subtree_unregistered,
&error);
@@ -658,6 +659,7 @@ test_object_registration (void)
registration_id = g_dbus_connection_register_subtree (c,
"/foo/boss/executives",
&subtree_vtable,
+ FALSE,
&data,
on_subtree_unregistered,
&error);
@@ -674,6 +676,7 @@ test_object_registration (void)
subtree_registration_id = g_dbus_connection_register_subtree (c,
"/foo/boss/executives",
&subtree_vtable,
+ FALSE,
&data,
on_subtree_unregistered,
&error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]