D-Bus testing: more efficient runUntil

An different approach is taken when runUntil() is called with
may_block=True: it lets the main loop run for 0.5 seconds and then
returns to do the status checking. No logging is done for each check.
This is meant for long-running operations where the 0.5 second latency
doesn't matter and too frequent checking and logging cause overhead.

The default code path checks every 0.1 second and recognizes
progress (defined as "there was an event to be processed"), which then
causes debug logging about waiting.
This commit is contained in:
Patrick Ohly 2013-02-15 09:27:37 +01:00
parent 1c125ac680
commit 9156ff3598
1 changed files with 33 additions and 15 deletions

View File

@ -40,6 +40,7 @@ import dbus
from dbus.mainloop.glib import DBusGMainLoop
import dbus.service
import gobject
import glib
import sys
import traceback
import re
@ -648,25 +649,42 @@ class DBusUtil(Timeout):
logging.log(message)
loop.get_context().iteration(may_block)
def runUntil(self, state, check, until):
def runUntil(self, state, check, until, may_block=False):
'''Loop until 'check' throws an exception or 'until' returns True.
Use check=lambda: (expr1, expr2, ...) when more than one check is needed.
'''
message = 'waiting for ' + state
printMessage = True
while True:
# Only print it if something changed, not every 0.1 second.
if printMessage:
printMessage = False
logging.log(message)
check()
if until():
break
# Don't block forever if nothing is to be processed.
# To keep the load down, sleep for a short period.
time.sleep(0.1)
if self.loopIteration(None, may_block=False):
printMessage = True
if may_block:
# Allow process to get stuck for a while.
# Return from the loop every half second to
# check status.
logging.log(message)
t = glib.Timeout(500)
try:
t.set_callback(lambda: loop.quit() or True)
t.attach(loop.get_context())
while True:
check()
if until():
break
loop.run()
finally:
t.destroy()
else:
progress = True
while True:
# Only print it if something changed, not every 0.1 second.
if progress:
logging.log(message)
check()
if until():
break
if not progress and not may_block:
# Don't block forever if nothing is to be processed.
# To keep the load down, sleep for a short period.
time.sleep(0.1)
progress = self.loopIteration(None, may_block=False)
logging.log('succeeded waiting for ' + state)
def isServerRunning(self):
"""True while the syncevo-dbus-server executable is still running"""