Re: EggDBus



On Mon, 2008-12-22 at 12:30 +0100, Murray Cumming wrote:
> This sounds wonderful. I have a couple of questions, though I am not
> very experienced with D-Bus.
> 
> >  o Each D-Bus interface maps to a GInterface
> 
> So you can get a GSomething object that is a proxy for D-Bus object,
> which implements GInterfaces for each D-Bus interface offered by that
> object?

There's an object proxy class (that in a sense is a final class) for
each remote object; you get instances of these from the connection
class; for example

 EggDBusObjectProxy *object_proxy;

 object_proxy = egg_dbus_connection_get_object_proxy (connection,
                                         "org.fd.DeviceKit.Disks",
                                         "/org/fd/disks/sda1");

Note that this call doesn't do any IO at all. It will however trigger a
few async calls to add signal match rules and to start tracking who owns
the name org.fd.DeviceKit.Disks (reflected in the property with the name
EggDBusObjectProxy:name-owner).

Now, you can't use this object to access any of the D-Bus interfaces;
you'll have to use the supplied QUERY_INTERFACE macro for each of the
generated interfaces to get an interface proxy. For example

 DevkitDevice *device;

 device = DEVKIT_QUERY_INTERFACE_DEVICE (object_proxy);
 /* get properties */
 g_object_get (device, "unix-block-device", block_device, NULL);
 /* ... or connect to signals */
 g_signal_connect (device, "some-signal", cb, NULL);
 /* ... or invoke methods */
 devkit_device_mount (...);

The interface proxies are owned by the object proxy and created on a
per-demand basis. E.g. if you never use an interface, you don't get to
pay overhead.

> And it discovers all those interfaces at instantiation (or code
> generation, though that leaves less runtime flexibility?), without each
> interface having to be individually requested asynchronously? That would
> be nice. 

Interface proxies are created on demand; e.g. only when used. There's no
automatic discovery happening.. there is however an easy to use
introspection facility

http://people.freedesktop.org/~david/eggdbus-0.1-docs/EggDBusObjectProxy.html#egg-dbus-object-proxy-introspect

that you can use to discover the available interfaces of a remote
object.

> 
> >    - each D-Bus property maps to
> >      - A GObject property, e.g.
> >        - com.example.Tweak.SomeReadWritePropety -> 
> >          TestTweak:some-read-write-property
> >        - C getters and setters (depending on the property access flags)
> 
> Isn't D-Bus property getting and setting asynchronous? How can this work
> with the non-async g_object_get() function?

Right now the first property_get() call on an interface proxy will
synchronously invoke (blocking in libdbus on the dbus fd, not blocking
in the main loop because that would cause reentrancy issues) the
GetAll() method on the org.fd.DBus.Properties interface. 

So it will be a bit slow on the first call (but I have plans to
speculative get all properties at interface proxy construction time) but
on subsequent calls it's fast as all properties are cached. In reality I
think this kind of behavior is probably fine; it's what most D-Bus
clients in the wild does anyway.

(FWIW, I have an item on the TODO list to asynchronously get an
interface proxy or at least have some way to get a notification when
D-Bus properties are available.)

Setting a property currently involves doing a sync call from
property_set() that blocks until the server acknowledges the write with
a reply. I have a TODO item to make this async but it's hard (though not
impossible) to implement correctly because of coherency issues. Note
that there's very few services in the wild with writable properties.

For changes, there's unfortunately no Changed() signal on the official
org.fd.DBus.Properties interface. For now I'm using a signal called
EggDBusChanged()) on said interface (embrace and extend!); FWIW, I'm
going to propose the Changed() signal on the D-Bus list.

So right now property handling is only 100% transparent when both the
server and the client is using EggDBus.

Note that most existing services has some kind of D-Bus signal to notify
apps of changes; you can connect to this signal and manually call

 egg_dbus_object_proxy_invalidate_properties()

to invalidate properties.

It's not impossible we want to pass a set of flags when creating proxies
to make some of this easier on the programmer (we probably also want
other flags to tune performance, see the TODO list for details), e.g. 

 object_proxy = egg_dbus_connection_get_object_proxy (connection,
     EGG_DBUS_OBJECT_PROXY_NEVER_CACHE_PROPERTIES,
     "org.fd.DeviceKit.Disks",
     "/org/fd/disks/sda1");

Yes, it's a little messy dealing with this. But once we get a Changed()
signal on the org.fd.DBus.Properties interface things should start
getting much better. FWIW, I just added this item to the TODO list

http://cgit.freedesktop.org/~david/eggdbus/commit/?id=894597618a3ede6b767fec7f3f698b1647786231

about interoperability.

>  Or do we need to use extra
> getter/setter functions to do this asynchronously?

You can always use

http://people.freedesktop.org/~david/eggdbus-0.1-docs/eggdbus-eggdbusproperties.html

to access properties and just bypass the GObject properties on the
interface proxy. For example, if property setting/getting can fail [1],
you need to use this.

     David

[1] : I'd argue that if property get/set can fail, then the provider of
the D-Bus service is doing something wrong and it shouldn't be a
property in the first place. But, hey, things like this can happen.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]