On Mon, 2009-11-16 at 22:38 +0100, Patrick Ohly wrote:
> * I can't seem to get StatusChanged from Session B in this
case:
> - session A starts syncing
> - session B starts
> - session A stops syncing, detaches
> I expected to get StatusChanged "idle" for B but I don't
I need to check this. The problem is that my test case for this
depends
on glib mainloop bindings in a python-gobject release that is so
recent
that Debian Stable (on my laptop) doesn't have it.
The tests now work without glib, so I can run this test again. I noticed
that it succeeded for the wrong reason, because of a timeout and not
because it successfully received the SessionChanged signal.
The problem in the test was that it registered the handler for
org.syncevolution.Server and the session path as object path. But the
signal is fired with "/org/syncevolution/Server" as path and the session
path as parameter of the signal.
However, this is unrelated to Jussi's problem. None of the tests check
for StatusChanged. The question is: what is the correct way of waiting
for a session to be ready for use?
One way is the SessionChanged signal. The server documentation says:
<doc:para>
To be notified when a session is ready for use, subscribe to
the SessionChanged signal before asking for a session. It
may fire before the request to create a session returns. Either
handle that or use Session.GetStatus() to check whether the
session is still "queueing".
</doc:para>
The Python code which creates a session looks like this:
def createSession(self, config, wait):
"""Return sessionpath and session object for session using
'config'.
A signal handler calls loop.quit() when this session becomes ready.
If wait=True, then this call blocks until the session is ready.
"""
sessionpath = self.server.StartSession(config)
def session_ready(object, ready):
print "session_ready", self, self.running, object, ready
if self.running and ready and object == sessionpath:
DBusUtil.quit_events.append("session " + object + "
ready")
loop.quit()
bus.add_signal_receiver(session_ready,
'SessionChanged',
'org.syncevolution.Server',
'org.syncevolution',
None,
byte_arrays=True,
utf8_strings=True)
session = dbus.Interface(bus.get_object('org.syncevolution',
sessionpath),
'org.syncevolution.Session')
status, error, sources = session.GetStatus(utf8_strings=True)
if wait and status == "queuing":
loop.run()
self.failUnlessEqual(DBusUtil.quit_events, ["session " + sessionpath
+ " ready"])
DBusUtil.quit_events = []
return (sessionpath, session)
In practice, when creating a session in an empty server, the signal is
indeed sent from inside the StartSession() implementation and thus
before the Python code registers the handler. The signal is never seen
by the code but his doesn't matter, because the status check lets the
function return without waiting.
Now, about StatusChanged "idle":
<doc:doc><doc:description>
<doc:para>A Session object is used to do do syncs and to modify the server
configurations. Clients can create a Session with Server.StartSession() and detach from it
with Session.Detach().</doc:para>
<doc:para>Commands (other than Detach()) cannot be used before the status
changes to "idle" (see GetStatus() and StatusChanged).</doc:para>
</doc:description></doc:doc>
So waiting for StatusChanged "idle" should indeed also work, *as long
as* the client checks the status before waiting for the signal, as for
SessionChanged above. Jussi, are you doing this?
Looking at my tests I can reproduce that StatusChanged is not sent.
Indeed, the source doesn't contain a transition from QUEUEING to IDLE.
It doesn't even have a QUEUEING state at all, all sessions start as
IDLE. That's not correct. I'm going to fix this together with writing a
test.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.