Patrick Ohly wrote:
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?
I always do a GetX after subscribing to XChanged, just to be extra sure.
This is how I use the various signals, just for your information:
I use Server.GetSessions and Server.SessionChanged to find out if any
session is running, to setup correct titles, show progress widgets,
enable/disable various buttons, etc. I then use Session.StatusChanged,
Session.GetStatus, Session.ProgressChanged and Session.GetProgress to
monitor the error state and progress of the currently running session.
In addition to this, when I start my own session (either when syncing or
when I need to modify configuration), I use Session.StatusChanged and
Session.GetStatus to find out when I'm "idle" and can start doing my
thing. Usually I'm "idle" right away as currently I only ask for a
session when there are no other sessions -- this may change but I think
it's a better user experience that way.
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.
Great, thanks!
Jussi