Add xyz.openbmc_project.ObjectMapper.Private
The mapper client bindings currently use the NameOwnerChanged
signal as a trigger for a mapper query when waiting for an
object to appear on the bus. This works because at the moment
the mapper returns a busy response to clients in the window
between NameOwnerChanged and completion of its discovery.
A forthcoming patch will change this behavior such that the
mapper will go ahead and respond in the window to improve
overall mapper responsiveness, at the cost of the current
causal ordering guarantee.
The ordering guarantee is what allows the current wait binding
implementation to work. Without it, the wait binding requires
a means to determine when it is safe to make a make a query.
Add a new mapper interface xyz.openbmc_project.ObjectMapper.Private
with a single signal IntrospectionComplete to meet this
requirement. "Private" because the signal should only be
consumed by the mapper client bindings.
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Change-Id: Ia7b65cd7edd37c49fa7b5ad808b0c59304c68717
diff --git a/libmapper/mapper.c b/libmapper/mapper.c
index 81df03d..962b4e0 100644
--- a/libmapper/mapper.c
+++ b/libmapper/mapper.c
@@ -24,12 +24,11 @@
#include <systemd/sd-event.h>
#include "mapper.h"
-static const char *async_wait_name_owner_match =
+static const char *async_wait_introspection_match =
"type='signal',"
- "sender='org.freedesktop.DBus',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged',"
- "path='/org/freedesktop/DBus'";
+ "sender='xyz.openbmc_project.ObjectMapper',"
+ "interface='xyz.openbmc_project.ObjectMapper.Private',"
+ "member='IntrospectionComplete'";
static const char *async_wait_interfaces_added_match =
"type='signal',"
@@ -46,7 +45,7 @@
void *userdata;
sd_event *loop;
sd_bus *conn;
- sd_bus_slot *name_owner_slot;
+ sd_bus_slot *introspection_slot;
sd_bus_slot *intf_slot;
int *status;
int count;
@@ -62,9 +61,7 @@
int retry;
};
-static int async_wait_match_name_owner_changed(sd_bus_message *, void *,
- sd_bus_error *);
-static int async_wait_match_interfaces_added(sd_bus_message *, void *,
+static int async_wait_match_introspection_complete(sd_bus_message *, void *,
sd_bus_error *);
static int async_wait_check_done(mapper_async_wait *);
static void async_wait_done(int r, mapper_async_wait *);
@@ -244,7 +241,7 @@
return 0;
}
-static int async_wait_match_name_owner_changed(sd_bus_message *m, void *w,
+static int async_wait_match_introspection_complete(sd_bus_message *m, void *w,
sd_bus_error *e)
{
int r;
@@ -260,42 +257,13 @@
return 0;
}
-static int async_wait_match_interfaces_added(sd_bus_message *m, void *w,
- sd_bus_error *e)
-{
- int i, r;
- mapper_async_wait *wait = w;
- const char *path;
-
- if(wait->finished)
- return 0;
-
- r = sd_bus_message_read(m, "o", &path);
- if (r < 0) {
- fprintf(stderr, "Error reading message: %s\n",
- strerror(-r));
- goto finished;
- }
-
- for(i=0; i<wait->count; ++i) {
- if(!strcmp(path, wait->objs[i]))
- wait->status[i] = 1;
- }
-
-finished:
- if(r < 0 || async_wait_check_done(wait))
- async_wait_done(r < 0 ? r : 0, wait);
-
- return 0;
-}
-
static void async_wait_done(int r, mapper_async_wait *w)
{
if(w->finished)
return;
w->finished = 1;
- sd_bus_slot_unref(w->name_owner_slot);
+ sd_bus_slot_unref(w->introspection_slot);
sd_bus_slot_unref(w->intf_slot);
if(w->callback)
@@ -360,10 +328,10 @@
memset(wait->status, 0, sizeof(*wait->status) * wait->count);
r = sd_bus_add_match(conn,
- &wait->name_owner_slot,
- async_wait_name_owner_match,
- async_wait_match_name_owner_changed,
- wait);
+ &wait->introspection_slot,
+ async_wait_introspection_match,
+ async_wait_match_introspection_complete,
+ wait);
if(r < 0) {
fprintf(stderr, "Error adding match rule: %s\n",
strerror(-r));
@@ -373,7 +341,7 @@
r = sd_bus_add_match(conn,
&wait->intf_slot,
async_wait_interfaces_added_match,
- async_wait_match_interfaces_added,
+ async_wait_match_introspection_complete,
wait);
if(r < 0) {
fprintf(stderr, "Error adding match rule: %s\n",
@@ -395,7 +363,7 @@
unref_intf_slot:
sd_bus_slot_unref(wait->intf_slot);
unref_name_slot:
- sd_bus_slot_unref(wait->name_owner_slot);
+ sd_bus_slot_unref(wait->introspection_slot);
free_status:
free(wait->status);
free_objs:
diff --git a/obmc/mapper/server.py b/obmc/mapper/server.py
index 8247568..fba4c9b 100644
--- a/obmc/mapper/server.py
+++ b/obmc/mapper/server.py
@@ -286,6 +286,7 @@
for x in pending:
x()
+ self.IntrospectionComplete(owner)
def discovery_error(self, owner, path, e):
if owner in self.defer_signals:
@@ -737,6 +738,10 @@
return self.filter_interfaces(list(objs.iteritems()), interfaces)
+ @dbus.service.signal(obmc.mapper.MAPPER_IFACE + '.Private', 's')
+ def IntrospectionComplete(self, name):
+ pass
+
def server_main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
diff --git a/obmc/mapper/utils.py b/obmc/mapper/utils.py
index 706cc61..3937cf6 100644
--- a/obmc/mapper/utils.py
+++ b/obmc/mapper/utils.py
@@ -40,16 +40,14 @@
self.waitlist_keyword = kw.pop('waitlist_keyword', None)
self.bus.add_signal_receiver(
- self.name_owner_changed_handler,
- dbus_interface=dbus.BUS_DAEMON_IFACE,
- signal_name='NameOwnerChanged')
+ self.introspection_handler,
+ dbus_interface=obmc.mapper.MAPPER_IFACE + '.Private',
+ signal_name='IntrospectionComplete')
self.bus.add_signal_receiver(
- self.interfaces_added_handler,
- dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
- sender_keyword='sender',
- signal_name='InterfacesAdded')
+ self.introspection_handler,
+ dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager')
- self.name_owner_changed_handler()
+ self.introspection_handler()
@staticmethod
def default_error(e):
@@ -61,11 +59,11 @@
self.done = True
self.bus.remove_signal_receiver(
- self.name_owner_changed_handler,
- dbus_interface=dbus.BUS_DAEMON_IFACE,
- signal_name='NameOwnerChanged')
+ self.introspection_handler,
+ dbus_interface=obmc.mapper.MAPPER_IFACE + '.Private',
+ signal_name='IntrospectionComplete')
self.bus.remove_signal_receiver(
- self.interfaces_added_handler,
+ self.introspection_handler,
dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
signal_name='InterfacesAdded')
@@ -119,18 +117,10 @@
self.waitlist[path] = list(info)[0]
self.check_done()
- def name_owner_changed_handler(self, *a, **kw):
+ def introspection_handler(self, *a, **kw):
if self.done:
return
for path in filter(
lambda x: not self.waitlist[x], self.waitlist.keys()):
self.get_object_async(path, 0)
-
- def interfaces_added_handler(self, path, *a, **kw):
- if self.done:
- return
-
- if path in self.waitlist.keys():
- self.waitlist[path] = kw['sender']
- self.check_done()