Nir Soffer has uploaded a new change for review.
Change subject: schedule: Introduce scheduling libary ......................................................................
schedule: Introduce scheduling libary
This moudule provides a Scheduler class scheduling execution of callables on a background thread.
This should be part of the new scalable vm sampling implemntation, and can be used also whenever you like to perform a short task on a background thread, without waiting for the completion of the task.
See the module docstring and tests for usage examples.
Change-Id: Ie3764806d93bd37c3b5924080eb5ae4d29e4f4e0 Signed-off-by: Nir Soffer nsoffer@redhat.com --- M debian/vdsm-python.install M lib/vdsm/Makefile.am A lib/vdsm/schedule.py M tests/Makefile.am A tests/scheduleTests.py M vdsm.spec.in 6 files changed, 346 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/29607/1
diff --git a/debian/vdsm-python.install b/debian/vdsm-python.install index 2d4bba6..1775241 100644 --- a/debian/vdsm-python.install +++ b/debian/vdsm-python.install @@ -16,6 +16,7 @@ ./usr/lib/python2.7/dist-packages/vdsm/netlink/link.py ./usr/lib/python2.7/dist-packages/vdsm/profile.py ./usr/lib/python2.7/dist-packages/vdsm/qemuimg.py +./usr/lib/python2.7/dist-packages/vdsm/schedule.py ./usr/lib/python2.7/dist-packages/vdsm/sslutils.py ./usr/lib/python2.7/dist-packages/vdsm/tool/__init__.py ./usr/lib/python2.7/dist-packages/vdsm/tool/dummybr.py diff --git a/lib/vdsm/Makefile.am b/lib/vdsm/Makefile.am index c074bb3..89a5573 100644 --- a/lib/vdsm/Makefile.am +++ b/lib/vdsm/Makefile.am @@ -32,6 +32,7 @@ netinfo.py \ profile.py \ qemuimg.py \ + schedule.py \ SecureXMLRPCServer.py \ sslutils.py \ utils.py \ diff --git a/lib/vdsm/schedule.py b/lib/vdsm/schedule.py new file mode 100644 index 0000000..bd75924 --- /dev/null +++ b/lib/vdsm/schedule.py @@ -0,0 +1,213 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Refer to the README and COPYING files for full details of the license +# + +""" +This module provides a Scheduler class scheduling execution of +a callable on a background thread. + +To use a scheduler, create an instance: + + scheduler = schedule.Scheduler() + +When you want to schedule some callable: + + def task(): + print '30 seconds passed' + + scheduler.schedule(30.0, task) + +task will be called after 30.0 seconds on the scheduler background thread. + +If you need to cancel a scheduled call, keep the ScheduledCall object returned +from Scheduler.schedule(), and cancel the task: + + scheduled_call = scheduler.schedule(30.0, call) + ... + scheduled_call.cancel() + +Finally, when the scheduler is not needed any more: + + scheduler.cancel() + +This will cancel any pending calls and terminate the scheduler thread. +""" + +import heapq +import logging +import threading +import time + +from . import utils + + +class Scheduler(object): + """ + Schedule calls for future execution in a background thread. + + This class is thread safe; multiple threads can schedule calls or cancel + the scheudler. + """ + + DEFAULT_DELAY = 30.0 # Used if no timeout are scheduled + + _log = logging.getLogger("vds.Scheduler") + + def __init__(self): + self._log.debug("Starting scheduler") + self._cond = threading.Condition(threading.Lock()) + self._running = True + self._timeouts = [] + t = threading.Thread(target=self._run) + t.daemon = True + t.start() + + def schedule(self, delay, callee): + """ + Schedule callee to be called after delay seconds on the scheduler + thread. + + Callee must not block or take excessive time to complete. It it does + not finish quickly, it may delay other scheduled calls on the scheduler + thread. + + Returns a ScheduledCall that may be canceled if callee was not called + yet. + """ + deadline = time.time() + delay + timeout = _Timeout(deadline, callee) + self._log.debug("Schedulng %s", timeout) + with self._cond: + if self._running: + heapq.heappush(self._timeouts, timeout) + self._cond.notify() + else: + timeout.cancel() + return ScheduledCall(timeout) + + def cancel(self): + """ + Cancel all schedueld calls and invalidate the scheduler. Calls + scheduled after a scheduler was cancel will never be called. + """ + self._log.debug("Canceling scheduler") + with self._cond: + self._running = False + self._cond.notify() + + @utils.traceback(on=_log.name) + def _run(self): + try: + self._log.debug("started") + self._loop() + self._log.debug("canceled") + finally: + self._cleanup() + + def _loop(self): + while True: + with self._cond: + if not self._running: + return + delay = self._time_until_deadline() + if delay > 0.0: + self._cond.wait(delay) + if not self._running: + return + expired = self._pop_expired_timeouts() + for timeout in expired: + timeout.fire() + + def _time_until_deadline(self): + if self._timeouts: + return self._timeouts[0].deadline - time.time() + return self.DEFAULT_DELAY + + def _pop_expired_timeouts(self): + now = time.time() + expired = [] + while self._timeouts: + timeout = self._timeouts[0] + if timeout.deadline > now: + break + heapq.heappop(self._timeouts) + expired.append(timeout) + return expired + + def _cleanup(self): + # Help the garbage collector by breaking reference cycles + with self._cond: + for timeout in self._timeouts: + timeout.cancel() + + +class ScheduledCall(object): + """ + Returned when a callable is scheduled to be called after delay. The caller + may cancel the call if it was not called yet. + + This class is thread safe; any thread can cacnel a call. + """ + + _log = logging.getLogger("vds.Scheduler") + + def __init__(self, timeout): + self._timeout = timeout + + @property + def deadline(self): + return self._timeout.deadline + + def cancel(self): + self._log.debug("Canceling %s", self) + self._timeout.cancel() + + +# Sentinel for marking timeouts as invalid. Callable so we can invaliate a +# timeout in a thread safe manner without locks. +def _INVALID(): + pass + + +class _Timeout(object): + """ + Created for each scheduled call. + """ + + _log = logging.getLogger('vds.Timeout') + + def __init__(self, deadline, callee): + self.deadline = deadline + self.callee = callee + + def fire(self): + if self.callee is _INVALID: + return + try: + self.callee() + except Exception: + self._log.exception("Unhandled exception in scheduled call") + finally: + self.callee = _INVALID + + def cancel(self): + self.callee = _INVALID + + def __cmp__(self, other): + return cmp(self.deadline, other.deadline) diff --git a/tests/Makefile.am b/tests/Makefile.am index 6507165..786dea4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -65,6 +65,7 @@ remoteFileHandlerTests.py \ resourceManagerTests.py \ samplingTests.py \ + scheduleTests.py \ schemaTests.py \ securableTests.py \ sslTests.py \ diff --git a/tests/scheduleTests.py b/tests/scheduleTests.py new file mode 100644 index 0000000..0c370d9 --- /dev/null +++ b/tests/scheduleTests.py @@ -0,0 +1,129 @@ +# +# Copyright 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# Refer to the README and COPYING files for full details of the license +# + +import threading +import time + +from vdsm import schedule +from testrunner import VdsmTestCase + + +class SchedulerTests(VdsmTestCase): + + # Time to wait for completion, so test will not fail on overloaded + # machines. If tests fails on CI, increase this value. + GRACETIME = 0.1 + + MAX_TASKS = 1000 + + def setUp(self): + self.scheduler = schedule.Scheduler() + + def tearDown(self): + self.scheduler.cancel() + + def test_schedule(self): + delay = 0.3 + task1 = Task() + task2 = Task() + timeout1 = self.scheduler.schedule(delay, task1) + self.scheduler.schedule(10, task2) + task1.wait(delay + self.GRACETIME) + self.assertTrue(timeout1.deadline <= task1.call_time) + self.assertTrue(task1.call_time < timeout1.deadline + self.GRACETIME) + self.assertEquals(task2.call_time, None) + + def test_schedule_many(self): + delay = 0.3 + tasks = [] + for i in range(self.MAX_TASKS): + task = Task() + timeout = self.scheduler.schedule(delay, task) + tasks.append((task, timeout)) + last_task = tasks[-1][0] + last_task.wait(delay + self.GRACETIME) + for task, timeout in tasks: + self.assertTrue(timeout.deadline <= task.call_time) + self.assertTrue(task.call_time < timeout.deadline + self.GRACETIME) + + def test_continue_after_failures(self): + self.scheduler.schedule(0.3, FailingTask()) + task = Task() + self.scheduler.schedule(0.4, task) + task.wait(0.4 + self.GRACETIME) + self.assertTrue(task.call_time is not None) + + def test_cancel_timeout(self): + delay = 0.3 + task = Task() + timeout = self.scheduler.schedule(delay, task) + timeout.cancel() + task.wait(delay + self.GRACETIME) + self.assertEquals(task.call_time, None) + + def test_cancel_many(self): + delay = 0.3 + tasks = [] + for i in range(self.MAX_TASKS): + task = Task() + timeout = self.scheduler.schedule(delay, task) + tasks.append((task, timeout)) + for task, timeout in tasks: + timeout.cancel() + last_task = tasks[-1][0] + last_task.wait(delay + self.GRACETIME) + for task, timeout in tasks: + self.assertEquals(task.call_time, None) + + def test_cancel(self): + delay = 0.3 + tasks = [] + for i in range(self.MAX_TASKS): + task = Task() + timeout = self.scheduler.schedule(delay, task) + tasks.append((task, timeout)) + self.scheduler.cancel() + last_task = tasks[-1][0] + last_task.wait(delay + self.GRACETIME) + for task, timeout in tasks: + self.assertEquals(task.call_time, None) + + +class Task(object): + + def __init__(self): + self.cond = threading.Condition(threading.Lock()) + self.call_time = None + + def __call__(self): + with self.cond: + self.call_time = time.time() + self.cond.notify() + + def wait(self, timeout): + with self.cond: + if self.call_time is None: + self.cond.wait(timeout) + + +class FailingTask(object): + + def __call__(self): + raise Exception("This task is broken") diff --git a/vdsm.spec.in b/vdsm.spec.in index dfca5bd..8ba0477 100644 --- a/vdsm.spec.in +++ b/vdsm.spec.in @@ -1163,6 +1163,7 @@ %{python_sitearch}/%{vdsm_name}/qemuimg.py* %{python_sitearch}/%{vdsm_name}/SecureXMLRPCServer.py* %{python_sitearch}/%{vdsm_name}/netconfpersistence.py* +%{python_sitearch}/%{vdsm_name}/schedule.py* %{python_sitearch}/%{vdsm_name}/sslutils.py* %{python_sitearch}/%{vdsm_name}/utils.py* %{python_sitearch}/%{vdsm_name}/vdscli.py*
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 1:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/9971/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10756/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/71/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/104... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/83/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/10913/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 2:
This version improves the tests.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 2:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/9972/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10757/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/72/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/105... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/84/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/10914/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 2:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/9972/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10757/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/105... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/84/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/10914/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/73/ : FAILURE
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
This version removes unused temporary variables introduced in the previous version.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/9973/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10758/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/74/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/106... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/85/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/10915/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
At glance looks really nice code, probably deserves its own private package (like zombiereaper). Will review later.
Saggi Mizrahi has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3: Code-Review-1
(13 comments)
I also prefer using_underscores but mixedCase is how things are in VDSM.
http://gerrit.ovirt.org/#/c/29607/3/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no timeout are scheduled Line 69: Line 70: _log = logging.getLogger("vds.Scheduler") Just 'Scheduler' or at the least 'vdsm.Scheduler' Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
Line 70: _log = logging.getLogger("vds.Scheduler") Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock()) Just use an empty ctor. Why overcomplicate? Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True
Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock()) Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run) Please name the thread. Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee): callee should be callable or target to keep with the standard library's convention. Line 82: """ Line 83: Schedule callee to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._timeouts, timeout) Line 99: self._cond.notify() Line 100: else: I would raise an error since getting here is likely a bug. Line 101: timeout.cancel() Line 102: return ScheduledCall(timeout) Line 103: Line 104: def cancel(self):
Line 110: with self._cond: Line 111: self._running = False Line 112: self._cond.notify() Line 113: Line 114: @utils.traceback(on=_log.name) I don't like utils.traceback.
It's silly and should be removed from the codebase. It removes proper context from the log message and moves the intent to log to a weird place IMHO (the function deceleration) Please don't use it in anything that is going to become infra code. Line 115: def _run(self): Line 116: try: Line 117: self._log.debug("started") Line 118: self._loop()
Line 133: expired = self._pop_expired_timeouts() Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self): _mixedCase Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141:
Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts: I don't like implied False. Check what you mean to check. len(self._timeouts) > 0 Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self):
Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Just wait for eternity Line 141: Line 142: def _pop_expired_timeouts(self): Line 143: now = time.time() Line 144: expired = []
Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self): _mixedCase Line 143: now = time.time() Line 144: expired = [] Line 145: while self._timeouts: Line 146: timeout = self._timeouts[0]
Line 155: with self._cond: Line 156: for timeout in self._timeouts: Line 157: timeout.cancel() Line 158: Line 159: Seems like _Timeout and ScheduledCall are actually both ScheduledCall but one interface is for internal use and one is for external.
That is the problem with not having interfaces in python.
In any case having a class name _Timeout is a bit odd.
I'd call the internal one ScheduledCall and the public one ScheduledCallToken Line 160: class ScheduledCall(object): Line 161: """ Line 162: Returned when a callable is scheduled to be called after delay. The caller Line 163: may cancel the call if it was not called yet.
Line 196: self.deadline = deadline Line 197: self.callee = callee Line 198: Line 199: def fire(self): Line 200: if self.callee is _INVALID: Just don't check, making it a function was the correct thing to do. Line 201: return Line 202: try: Line 203: self.callee() Line 204: except Exception:
Line 201: return Line 202: try: Line 203: self.callee() Line 204: except Exception: Line 205: self._log.exception("Unhandled exception in scheduled call") exc_info Line 206: finally: Line 207: self.callee = _INVALID Line 208: Line 209: def cancel(self):
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
Saggi, new code in vdsm use pep8 style, for example: - vdsm/protocoldetector.py - http://gerrit.ovirt.org/29392
If most of us prefer this style, why should we punish ourself with the style of vdsm? The only person how likes this style is Ayal, and he is not contributing to vdsm lately :-)
I think we should keep current modules in the same style they are, and add new modules in pep8 style. But Dan prefer to add *all* new code in this style.
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
(13 comments)
Thanks for the quick review!
http://gerrit.ovirt.org/#/c/29607/3/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no timeout are scheduled Line 69: Line 70: _log = logging.getLogger("vds.Scheduler")
Just 'Scheduler' or at the least 'vdsm.Scheduler'
vds will inherit the vds logger configuration. We may want to change the behavior of infrastructure related logging.
Personally I like shorter logger names, but having common configuration is useful. Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
Line 70: _log = logging.getLogger("vds.Scheduler") Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
Just use an empty ctor. Why overcomplicate?
The default lock type is RLock, which is not needed in this case. Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True
Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock()) Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run)
Please name the thread.
Good idea.
I think we should do:
def __init__(self, name="Scheduler"): ... t = threading.Thread(target=self._run, name=name)
So if we start more then one scheduler, we can name them easily. Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
callee should be callable or target to keep with the standard library's con
I'll change to callable, hopefully Dan will not complain that it hides the builtin function :-) Line 82: """ Line 83: Schedule callee to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._timeouts, timeout) Line 99: self._cond.notify() Line 100: else:
I would raise an error since getting here is likely a bug.
This can be normal condition, you have one thread that does sampling, and another thread stop the scheduler, for example, during shutdown. In this case a traceback is unwanted, and we don't want to catch this error on all calls to the scheduler, to prevent bogus warnings on shutdown.
Maybe log a warning here? - this will help us fix bad code that use the scheduler when it should not. Line 101: timeout.cancel() Line 102: return ScheduledCall(timeout) Line 103: Line 104: def cancel(self):
Line 110: with self._cond: Line 111: self._running = False Line 112: self._cond.notify() Line 113: Line 114: @utils.traceback(on=_log.name)
I don't like utils.traceback.
Lets talk about the technical reasons.
This utility is critical to allow debugging when thread dies. This works even if the error handling code in the thread is broken, for example:
try: do stuff.. except Exception: self.log.debug("%s", nosuchname)
In this case we will get the name error in the log. Otherwise the thread will just die silently.
This utility was created per Federico request, when we tried to debug a domain monitor thread that was disappeared silently. This bug moved to infra and finally close without resolution. If we had this decorator there, we could solve the original issue.
If you want better log message, we can use the msg argument:
@utils.traceback(on=log.name, msg="whatever")
Or improve the decorator :-) Line 115: def _run(self): Line 116: try: Line 117: self._log.debug("started") Line 118: self._loop()
Line 133: expired = self._pop_expired_timeouts() Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self):
_mixedCase
pep8 Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141:
Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts:
I don't like implied False. Check what you mean to check.
I think this is little bit too noisy; this is the clearest way to say what I want to say in Python. Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self):
Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY
Just wait for eternity
This will complicate the calling code for no reason. I can change the default timeout to bigger value (e.g. 300) if you think that it make any difference. Line 141: Line 142: def _pop_expired_timeouts(self): Line 143: now = time.time() Line 144: expired = []
Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self):
_mixedCase
pep8 Line 143: now = time.time() Line 144: expired = [] Line 145: while self._timeouts: Line 146: timeout = self._timeouts[0]
Line 155: with self._cond: Line 156: for timeout in self._timeouts: Line 157: timeout.cancel() Line 158: Line 159:
Seems like _Timeout and ScheduledCall
ScheduledCallToken is too long and confusing - this is not a token. Token is not something that you cancel.
The public class is the what you return from schedule, so the name makes sense. The private one is related to the implementation, which use a list of timeouts.
Your view that both are actually the same class is correct, so we can use the same name:
- ScheculedCall - public - _ScheduledCall - private
And change _timeouts to _calls Line 160: class ScheduledCall(object): Line 161: """ Line 162: Returned when a callable is scheduled to be called after delay. The caller Line 163: may cancel the call if it was not called yet.
Line 196: self.deadline = deadline Line 197: self.callee = callee Line 198: Line 199: def fire(self): Line 200: if self.callee is _INVALID:
Just don't check, making it a function was the correct thing to do.
ok Line 201: return Line 202: try: Line 203: self.callee() Line 204: except Exception:
Line 201: return Line 202: try: Line 203: self.callee() Line 204: except Exception: Line 205: self._log.exception("Unhandled exception in scheduled call")
exc_info
This logs an exception - why do you want to add exc_info? Line 206: finally: Line 207: self.callee = _INVALID Line 208: Line 209: def cancel(self):
Saggi Mizrahi has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
(10 comments)
http://gerrit.ovirt.org/#/c/29607/3/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no timeout are scheduled Line 69: Line 70: _log = logging.getLogger("vds.Scheduler")
vds will inherit the vds logger configuration. We may want to change the be
I don't see why this needs to inherit the vds log configuration. Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
Line 70: _log = logging.getLogger("vds.Scheduler") Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
The default lock type is RLock, which is not needed in this case.
That's odd since using RLock and a Condition is highly frowned upon, but then again python was never known for being smart about it's sync primitives. Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True
Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock()) Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run)
Good idea.
I'm cool with that. Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
I'll change to callable, hopefully Dan will not complain that it hides the
Yea, it is a problem. But callee isn't really a word. I guess using target is the way to go. (similar to thread) Line 82: """ Line 83: Schedule callee to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._timeouts, timeout) Line 99: self._cond.notify() Line 100: else:
This can be normal condition, you have one thread that does sampling, and a
I'm ok with logging Line 101: timeout.cancel() Line 102: return ScheduledCall(timeout) Line 103: Line 104: def cancel(self):
Line 110: with self._cond: Line 111: self._running = False Line 112: self._cond.notify() Line 113: Line 114: @utils.traceback(on=_log.name)
Lets talk about the technical reasons.
The problem you are trying to fix is not an issue we should care about. Error with the log formatting are not issues that I need to expect.
If there is a bug in in the logging code it's something that needs to be fixed.
If we want to make sure exceptions in threads go to a logger instead of standard error that is a different problem all together.
log lines needs to be explicitly put near the issue. logging is never a property of the function, I know that there are places in the code were decorators are used for logging but they will need to be eventually removed.
Logging needs to be placed in a predictable place. Line 115: def _run(self): Line 116: try: Line 117: self._log.debug("started") Line 118: self._loop()
Line 133: expired = self._pop_expired_timeouts() Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self):
pep8
I prefer that style as well but I much rather have uniformity than adhere to a specific style. This kind of mixing might be tolerable in a strict language but with duck typing you are just making it harder for people to remember the function names. Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141:
Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts:
I think this is little bit too noisy; this is the clearest way to say what
That is how we do things. We had issues with that style of coding. We are not using it. Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self):
Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY
This will complicate the calling code for no reason. I can change the defau
Why would it complicate? Line 141: Line 142: def _pop_expired_timeouts(self): Line 143: now = time.time() Line 144: expired = []
Line 155: with self._cond: Line 156: for timeout in self._timeouts: Line 157: timeout.cancel() Line 158: Line 159:
ScheduledCallToken is too long and confusing - this is not a token. Token i
Token is the thing you hold. And I'm OK with that scheme as long as you document that one is the public interface since it's not immediately clear. Line 160: class ScheduledCall(object): Line 161: """ Line 162: Returned when a callable is scheduled to be called after delay. The caller Line 163: may cancel the call if it was not called yet.
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 3:
(8 comments)
http://gerrit.ovirt.org/#/c/29607/3/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no timeout are scheduled Line 69: Line 70: _log = logging.getLogger("vds.Scheduler")
I don't see why this needs to inherit the vds log configuration.
Done Line 71: Line 72: def __init__(self): Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock())
Line 73: self._log.debug("Starting scheduler") Line 74: self._cond = threading.Condition(threading.Lock()) Line 75: self._running = True Line 76: self._timeouts = [] Line 77: t = threading.Thread(target=self._run)
I'm cool with that.
Done Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
Line 77: t = threading.Thread(target=self._run) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callee):
Yea, it is a problem. But callee isn't really a word. I guess using target
Changed to callable, target is a poor name for something that you can call. Line 82: """ Line 83: Schedule callee to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._timeouts, timeout) Line 99: self._cond.notify() Line 100: else:
I'm ok with logging
Done Line 101: timeout.cancel() Line 102: return ScheduledCall(timeout) Line 103: Line 104: def cancel(self):
Line 110: with self._cond: Line 111: self._running = False Line 112: self._cond.notify() Line 113: Line 114: @utils.traceback(on=_log.name)
The problem you are trying to fix is not an issue we should care about. Err
I think that the traceback decorator is the best option for ensuring that thread main function always log fatal failures.
Adding explicit logging will required a second try except for every thread main function:
try: try: loop... finally: cleanup... except Exception: log exception
This bolierplate does not help anyone, and does not give more context - both will give the same useful traceback.
Lets see what others think about it. Line 115: def _run(self): Line 116: try: Line 117: self._log.debug("started") Line 118: self._loop()
Line 133: expired = self._pop_expired_timeouts() Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self):
I prefer that style as well but I much rather have uniformity than adhere t
But this is not a public api, nobody has to type this name. Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141:
Line 134: for timeout in expired: Line 135: timeout.fire() Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts:
That is how we do things. We had issues with that style of coding. We are n
I will use the more verbose way to keep you happy :-) Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY Line 141: Line 142: def _pop_expired_timeouts(self):
Line 136: Line 137: def _time_until_deadline(self): Line 138: if self._timeouts: Line 139: return self._timeouts[0].deadline - time.time() Line 140: return self.DEFAULT_DELAY
Why would it complicate?
The calling code get a value and wait only if the value is positive. This way we save a syscall when we have an expired timeout to fire, and the code is the most simple and clear that we can have.
The 30 seconds timeout does not have any effect on the system, it is equivalent to waiting for eternity. Line 141: Line 142: def _pop_expired_timeouts(self): Line 143: now = time.time() Line 144: expired = []
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
This version address Saggi comments, improve logging and tune test that was too stressful.
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4: Verified+1
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10120/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10905/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/97/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/129... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/108/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11062/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10120/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10905/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/129... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/108/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11062/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/98/ : FAILURE
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
(4 comments)
This could be an useful building block, but I have a couple of initial concerns, one minor and one major.
The minor one is this API, albeit nice, is reminiscent of the concurrent.futures (https://docs.python.org/3/library/concurrent.futures.html - backport for py2 available). Can be probably considered a subset of it. Maybe I'm biased towards this API, but I don't see the need to have a different one, and to carry more code on our shoulders; then, I'd like either to build on that API/code, maybe depending on the backport for the time being, or ot build a compatibility layer to behave like the futures (see http://gerrit.ovirt.org/#/c/29424/)
However, this is a minor concern. The major one is sadly we have to deal with possibly blocking calls, as I said inline, and this very code is built on the assumption that Scheduled code executes fast and do not block. I think it is hard to fix a blocked call from the outside without support of the executor code, this is why I added the supervisor and the thread replacement on my threadpool. Maybe this was a wrong approach, but this problem is real and I don't see yet how to tackle it with this code.
Please, let's discuss those major design goals/problems on devel@ovirt.org, as mailing lists is a more friendly to articulate thoughts.
http://gerrit.ovirt.org/#/c/29607/4/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 61: """ Line 62: Schedule calls for future execution in a background thread. Line 63: Line 64: This class is thread safe; multiple threads can schedule calls or cancel Line 65: the scheudler. typo: scheduler Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no call are scheduled Line 69:
Line 77: t = threading.Thread(target=self._run, name=name) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callable): 'callable' shadows a builtin, that is usually a thing to avoid Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85: Line 86: Callable must not block or take excessive time to complete. It it does Still, in sampling we can have calls that block, because some calls may need to access storage and/or the QEMU monitor and we cannot known in advance which one will block
Actually we can get useful information from a blocked call, this can be an useful additional indicator that the QEMU process is blocked/not responding, and this information must be reported
Even considering a single scheduler per sampling type -to minimize interferences between samplings- the fist storage-blocking call will hurt all the others. Line 87: not finish quickly, it may delay other scheduled calls on the scheduler Line 88: thread. Line 89: Line 90: Returns a ScheduledCall that may be canceled if callable was not called
Line 91: yet. Line 92: """ Line 93: deadline = time.time() + delay Line 94: call = _Call(deadline, callable) Line 95: self._log.debug("Schedulng %s", call) typo: scheduling Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._calls, call) Line 99: self._cond.notify()
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
(4 comments)
Francesco, see my response in the inline comment.
http://gerrit.ovirt.org/#/c/29607/4/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 61: """ Line 62: Schedule calls for future execution in a background thread. Line 63: Line 64: This class is thread safe; multiple threads can schedule calls or cancel Line 65: the scheudler.
typo: scheduler
Will fix Line 66: """ Line 67: Line 68: DEFAULT_DELAY = 30.0 # Used if no call are scheduled Line 69:
Line 77: t = threading.Thread(target=self._run, name=name) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callable):
'callable' shadows a builtin, that is usually a thing to avoid
Was callle before, changed to callable as Saggi suggested. This hides the builtin but this code does not use, so I'm fine with that.
Unless you come up with better name that is clear as "callable". Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85: Line 86: Callable must not block or take excessive time to complete. It it does
Still, in sampling we can have calls that block, because some calls may nee
You cannot call this if your call blocks. When used for sampling, you will schedule the call to put the task in the threadpool, which cannot block:
Here is an example Sampler to illustrate this usage:
class Sampler:
# Task interface
def execute(self): self.status = RUNNING self._collect_stats() self.scheduler.schedule(15, self.dispatch) self.status = WAITING
@property def status(self): return self.status
# Private
def _dispatch(self): self.threadpool.dispatch(self)
So there is no issue here, because handling calls that block is the responsibility of the caller. Line 87: not finish quickly, it may delay other scheduled calls on the scheduler Line 88: thread. Line 89: Line 90: Returns a ScheduledCall that may be canceled if callable was not called
Line 91: yet. Line 92: """ Line 93: deadline = time.time() + delay Line 94: call = _Call(deadline, callable) Line 95: self._log.debug("Schedulng %s", call)
typo: scheduling
Will fix Line 96: with self._cond: Line 97: if self._running: Line 98: heapq.heappush(self._calls, call) Line 99: self._cond.notify()
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
(2 comments)
http://gerrit.ovirt.org/#/c/29607/4/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 77: t = threading.Thread(target=self._run, name=name) Line 78: t.daemon = True Line 79: t.start() Line 80: Line 81: def schedule(self, delay, callable):
Was callle before, changed to callable as Saggi suggested. This hides the b
Fair enough. Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85:
Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85: Line 86: Callable must not block or take excessive time to complete. It it does
You cannot call this if your call blocks. When used for sampling, you will
Fine, but then what's the advantage of having a private executor thread inside the Scheduler?
Wouldn't that better if the Scheduler receives a reference to an executor, like for example a thread pool or anything which implements a given simple interface and just submits the callable to it?
This way is even simpler and more regular: scheduler just schedules and does no more; threadpool just executes and does no more. Line 87: not finish quickly, it may delay other scheduled calls on the scheduler Line 88: thread. Line 89: Line 90: Returns a ScheduledCall that may be canceled if callable was not called
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
(1 comment)
http://gerrit.ovirt.org/#/c/29607/4/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 82: """ Line 83: Schedule callable to be called after delay seconds on the scheduler Line 84: thread. Line 85: Line 86: Callable must not block or take excessive time to complete. It it does
Fine, but then what's the advantage of having a private executor thread ins
The advantage is that both scheduler and thread pool are decoupled, and you can build various solutions by mixing them or using them separately.
I prefer simple reusable parts that I can combine in smart ways over complex parts that I have to fight to make it do what I want and live with their bloat.
This achive your goals: - scheduler does only scheduling, does not now anything about executors/threadpools - threadpool/executor execute stuff
For example, lets say the thread pool as limited queue - who will handle the case where the queue is full?
We don't like the scheduler to deal with this, since it is not related to scheduling. *Your* code should deal with this case, therefore *your* code should schedule itself to dispatch a task on the threadpool, and it should know how to handle a full queue - for example, by delaying the scheduled task again, or failing, whatever. This is application policy and the scheduler does not care about it. Line 87: not finish quickly, it may delay other scheduled calls on the scheduler Line 88: thread. Line 89: Line 90: Returns a ScheduledCall that may be canceled if callable was not called
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
Francesco, I don't see how concurrent.futures (https://docs.python.org/3/library/concurrent.futures.html) is related to the scheduler. This is more related to the thread pool.
The main feature of future is waiting for future result. So you need waiting thread waiting on the future, while another thread run the operation. This means that you could run the original operation in the waiting thread. It seem to be useful when one thread is waitting for many threads to finish.
But in our case we want to have 100's of sampling objects, all running in the same thread. They are not waiting on anything, but keep the sate of the current and the next calls, and schedule themself to run the next call on the threadpool.
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
Nevermind, it's probably just a pet peeve of mine. Let's go ahead with Schedule, then.
Michal Skrivanek has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 4:
-please run though spell check, quite a lot of typos - i don't see it helping too much with the stats…it's nice to have though, we need to/want to schedule a stat after some time indeed, it will make for a better separation - it should go to utils
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 5:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10183/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/10968/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/104... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/135... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/114/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11125/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 5: Code-Review+1
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 6: Verified+1
Changes: - Spelling - Remove noisy when scheduling calls - this may happen every few milliseconds with 100's of vms.
Verified using the tests and the next patch.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 6:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10337/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11122/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/125... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/156... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/135/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11279/ : FAILURE
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 7:
Rebased my patches on top of Nir's. No code changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 7:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10354/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11139/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/132... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/163... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/142/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11295/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 8:
Rebase on master.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 8:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10372/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11157/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/136... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/167... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/146/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11314/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 9:
Changes: - Don't start scheduler thread when creating an object - this is almost always a bad idea, making it harder to use in a module context, as can be seen in earlier versions on the sampling patch. - Use standard start() stop() api instead of cancel() - Raise if trying to schedule calls on a scheduler which is not running, similar to the executor behavior, instead of logging warnings.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling libary ......................................................................
Patch Set 9:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10379/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11164/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/138... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/169... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/148/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11321/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 10:
fixed tiny typo in the commit message header. No code changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 10:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10382/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11167/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/139... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/170... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/149/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11323/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 11:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10473/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11258/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/160... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/191... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/170/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11415/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 12:
This version includes few optimizations based on profiling done in http://gerrit.ovirt.org/30987.
- Drop the useless user wrapper around a scheduled call. Now we create one object per call, and return it to the user to allow canceling. - Keep calls in tuple (dedaline, call), which makes heappush faster, since it does not have to invoke ScheduledCall.__cmp__ millions of times - Wakeup scheduler only if scheduled call was scheduled first. There is no reason to wake up the scheduler in other cases - Drop canceled calls when popping out expired calls, previouly were returned in the list of expired calls, and were executed (noop). - Remove deadline from ScheduledCall, as the deadline is stored in the tuple - Use __slots__ in ScheduledCall to minimize memory usage
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 12:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/194/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10611/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/184... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11553/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/215... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11396/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 12:
rebased
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 13:
rebased on today's master (and discard previous comment...)
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 13:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/215/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10708/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/205... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11650/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/237... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11493/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 14:
rebased. No code changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 14:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10754/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/214... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11696/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/246... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11539/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/228/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 14:
(3 comments)
http://gerrit.ovirt.org/#/c/29607/14/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 102: """ Line 103: Schedule callable to be called after delay seconds on the scheduler Line 104: thread. Line 105: Line 106: Callable must not block or take excessive time to complete. It it does
typo: It it does
Done Line 107: not finish quickly, it may delay other scheduled calls on the scheduler Line 108: thread. Line 109: Line 110: Returns a ScheduledCall that may be canceled if callable was not called
Line 164: Line 165: def _cancel_calls(self): Line 166: # Help the garbage collector by breaking reference cycles Line 167: with self._cond: Line 168: for deadline, call in self._calls:
why not just empty self._calls, like this: self._calls = []
Typically an object schedule a call and keep for one of its methods, and keep a reference to the scheduler. So we have this cycle:
obj -> scheduler -> calls -> scheduled_call -> method -> obj
cancel() remove method from the loop, breaking the cycle. Line 169: call.cancel() Line 170: Line 171: Line 172: class ScheduledCall(object):
Line 200: Line 201: Line 202: # Sentinel for marking calls as invalid. Callable so we can invalidate a call Line 203: # in a thread safe manner without locks. Line 204: def _INVALID():
Why uppercase?
This is a constant - you are not supposed to use this function. It is a function only to allow _execute to run without any racy checks.
For example, we could (wrongly) implement this with None:
def _execute(self): if self._callable is not None: self._callable()
But it is racy. Using a function solve this race, but is function is not part of the api of this module.
I think that nothing can be more clear than:
self._callable = _INVALID
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 15:
Fix typo in docstring.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 15:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10799/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/225... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11741/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/259... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11584/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/240/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 15:
(1 comment)
http://gerrit.ovirt.org/#/c/29607/15/tests/scheduleTests.py File tests/scheduleTests.py:
Line 135: min = clock.latency[0] Line 136: avg = sum(clock.latency) / len(clock.latency) Line 137: med = clock.latency[len(clock.latency) / 2] Line 138: max = clock.latency[-1] Line 139: print 'latency - avg: %.3f min: %.3f median: %.3f max: %.3f' % (
I didn't find any instructions which could tell me which version of python,
Currently VDSM is a python 2.6+ program. Line 140: avg, min, med, max) Line 141: # This may be too strict on overloaded machines. We may need to Line 142: # incrase this value if it breaks in the CI. On my laptop I get Line 143: # avg latency 1 millisecond.
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 15:
(2 comments)
http://gerrit.ovirt.org/#/c/29607/15/tests/scheduleTests.py File tests/scheduleTests.py:
Line 135: min = clock.latency[0] Line 136: avg = sum(clock.latency) / len(clock.latency) Line 137: med = clock.latency[len(clock.latency) / 2] Line 138: max = clock.latency[-1] Line 139: print 'latency - avg: %.3f min: %.3f median: %.3f max: %.3f' % (
I didn't find any instructions which could tell me which version of python,
print is not about personal preferences - I'm using what available and idiomatic in Python 2.6, which is the version available on EL 6, our main platform. Line 140: avg, min, med, max) Line 141: # This may be too strict on overloaded machines. We may need to Line 142: # incrase this value if it breaks in the CI. On my laptop I get Line 143: # avg latency 1 millisecond.
Line 138: max = clock.latency[-1] Line 139: print 'latency - avg: %.3f min: %.3f median: %.3f max: %.3f' % ( Line 140: avg, min, med, max) Line 141: # This may be too strict on overloaded machines. We may need to Line 142: # incrase this value if it breaks in the CI. On my laptop I get
typo:incrase
Done Line 143: # avg latency 1 millisecond. Line 144: self.assertTrue(max < 0.1) Line 145: Line 146:
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 16:
Fixed another typo in the tests - thanks jian wang!
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 16:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10840/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/232... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11782/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/266... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11625/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/247/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 18:
rebased. No code changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 17:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10888/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/237... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11830/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/271... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11673/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/252/ : SUCCESS
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 18:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/10896/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/239... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/11838/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc19_created/273... : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/11681/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/254/ : SUCCESS
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 18: Verified+1
this code passed several times of testing using 100 and 200 VMs, which is more than enough to consider it Verified for me.
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 19:
rebased with no code changes.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 19:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/128... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/694/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/13855/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/675... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/13066/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/14018/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/133/ : SUCCESS
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 20:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 20: Verified+1
rebased with no code changes. Copied score.
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 21:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 20:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/273... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/279/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/14877/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/838/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/14709/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/13921/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/821... : FAILURE
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 22:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 22:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/289... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/295/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/14976/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/854/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/14807/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/14019/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/836... : FAILURE
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 23:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Dan Kenigsberg has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 23: Code-Review-1
(2 comments)
only minor nit found - please implement with monotonic timeout.
http://gerrit.ovirt.org/#/c/29607/23/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 109: Line 110: Returns a ScheduledCall that may be canceled if callable was not called Line 111: yet. Line 112: """ Line 113: deadline = time.time() + delay now we can use monotonic_time(), just in case someone plays with the system date. Line 114: call = ScheduledCall(callable) Line 115: with self._cond: Line 116: if not self._running: Line 117: raise AssertionError("Scheduler not running")
Line 123: Line 124: @utils.traceback(on=_log.name) Line 125: def _run(self): Line 126: try: Line 127: self._log.debug("started") strictly speaking, first log should be out of the try block Line 128: self._loop() Line 129: self._log.debug("stopped") Line 130: finally: Line 131: self._cancel_calls()
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 23:
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/331... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/15211/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/896/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/15042/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/14254/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/879... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/338/ : SUCCESS
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 23:
(2 comments)
http://gerrit.ovirt.org/#/c/29607/23/lib/vdsm/schedule.py File lib/vdsm/schedule.py:
Line 109: Line 110: Returns a ScheduledCall that may be canceled if callable was not called Line 111: yet. Line 112: """ Line 113: deadline = time.time() + delay
now we can use monotonic_time(), just in case someone plays with the system
monotonic_time() resolution is only 10 milliseconds, so this will delay wakeups for no benefit most of the time. System time changes on a machine with ntp are practically non-issue in the context of this scheduler.
In python 3, we can use the real thing implemented with clock_gettime instead of our os.times hack. Line 114: call = ScheduledCall(callable) Line 115: with self._cond: Line 116: if not self._running: Line 117: raise AssertionError("Scheduler not running")
Line 123: Line 124: @utils.traceback(on=_log.name) Line 125: def _run(self): Line 126: try: Line 127: self._log.debug("started")
strictly speaking, first log should be out of the try block
Done Line 128: self._loop() Line 129: self._log.debug("stopped") Line 130: finally: Line 131: self._cancel_calls()
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24:
* Update tracker::IGNORE, no Bug-Url found * Check Bug-Url::WARN, no bug url found, make sure header matches 'Bug-Url: ' and is a valid url. * Check merged to previous::IGNORE, Not in stable branch (['ovirt-3.5', 'ovirt-3.4', 'ovirt-3.3'])
Nir Soffer has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24: Verified+1
This version adds a clock argument so the caller can use utils.monotonic_clock if desired.
The tests were update to test both time.time() and utils.monotonic_time().
The default clock is still time.time() since it is more precise then utils.monotonic_time. When we upgrade to Python 3 the default should be replaced to time.monotonic().
Verified using the tests.
oVirt Jenkins CI Server has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc21_created/338... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/15300/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/15131/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/14343/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-fc20_created/886... : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el7_created/345/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_install-rpm-sanity-el6_created/903/ : SUCCESS
Dan Kenigsberg has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24: Code-Review+2
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24: Code-Review+1
Francesco Romani has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 24:
Thanks Nir for the updates!
Dan Kenigsberg has submitted this change and it was merged.
Change subject: schedule: Introduce scheduling library ......................................................................
schedule: Introduce scheduling library
This moudule provides a Scheduler class scheduling execution of callables on a background thread. This should be part of the new scalable vm sampling implemntation.
See the module docstring and tests for usage examples.
Change-Id: Ie3764806d93bd37c3b5924080eb5ae4d29e4f4e0 Signed-off-by: Nir Soffer nsoffer@redhat.com Reviewed-on: http://gerrit.ovirt.org/29607 Reviewed-by: Dan Kenigsberg danken@redhat.com Reviewed-by: Francesco Romani fromani@redhat.com --- M debian/vdsm-python.install M lib/vdsm/Makefile.am A lib/vdsm/schedule.py M tests/Makefile.am A tests/scheduleTests.py M vdsm.spec.in 6 files changed, 441 insertions(+), 0 deletions(-)
Approvals: Nir Soffer: Verified Dan Kenigsberg: Looks good to me, approved Francesco Romani: Looks good to me, but someone else must approve
automation@ovirt.org has posted comments on this change.
Change subject: schedule: Introduce scheduling library ......................................................................
Patch Set 25:
* Update tracker::IGNORE, no Bug-Url found * Set MODIFIED::IGNORE, no Bug-Url found.
vdsm-patches@lists.fedorahosted.org