Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Use timestamp in loopingcall
Browse files Browse the repository at this point in the history
All time related data in loopingcall are in seconds.
Therefore creating datetime objects only adds overhead to the module.
This patch replaces all datetime objects with utc timestamps in loopingcall.

The rational of using timeutils was disscussed here,
https://review.openstack.org/#/c/16310/1..5/openstack/common/loopingcall.py,cm
which was to use set_time_override to avoid actual time delays in test scripts.
Now that set_time_override is deprecated, we no longer need to use timeutils.

A lambda function returning time.time() was declared due to mock collisions
with time.time() called in the logging module.
Changes to test scripts were made accordingly.

Change-Id: I38749f3c7bfff23164481b2341d56154ba737765
  • Loading branch information
Zhongyue Luo committed Jul 2, 2014
1 parent fd90c34 commit ab5d5f1
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 18 deletions.
15 changes: 10 additions & 5 deletions openstack/common/loopingcall.py
Expand Up @@ -16,16 +16,21 @@
# under the License.

import sys
import time

from eventlet import event
from eventlet import greenthread

from openstack.common.gettextutils import _LE, _LW
from openstack.common import log as logging
from openstack.common import timeutils

LOG = logging.getLogger(__name__)

# NOTE(zyluo): This lambda function was declared to avoid mocking collisions
# with time.time() called in the standard logging module
# during unittests.
_ts = lambda: time.time()


class LoopingCallDone(Exception):
"""Exception to break out and stop a LoopingCallBase.
Expand Down Expand Up @@ -72,15 +77,15 @@ def _inner():

try:
while self._running:
start = timeutils.utcnow()
start = _ts()
self.f(*self.args, **self.kw)
end = timeutils.utcnow()
end = _ts()
if not self._running:
break
delay = interval - timeutils.delta_seconds(start, end)
delay = interval + start - end
if delay <= 0:
LOG.warn(_LW('task %(func_name)s run outlasted '
'interval by %(delay)s sec'),
'interval by %(delay).2f sec'),
{'func_name': repr(self.f), 'delay': -delay})
greenthread.sleep(delay if delay > 0 else 0)
except LoopingCallDone as e:
Expand Down
25 changes: 12 additions & 13 deletions tests/unit/test_loopingcall.py
Expand Up @@ -12,14 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.

import datetime
import time

from eventlet import greenthread
from oslotest import base as test_base
from six.moves import mox

from openstack.common import loopingcall
from openstack.common import timeutils


class LoopingCallTestCase(test_base.BaseTestCase):
Expand Down Expand Up @@ -59,23 +58,23 @@ def test_interval_adjustment(self):
"""Ensure the interval is adjusted to account for task duration."""
self.num_runs = 3

now = datetime.datetime.utcnow()
second = datetime.timedelta(seconds=1)
smidgen = datetime.timedelta(microseconds=10000)
now = time.time()
second = 1
smidgen = 0.01

m = mox.Mox()
m.StubOutWithMock(greenthread, 'sleep')
greenthread.sleep(mox.IsAlmost(0.02))
greenthread.sleep(mox.IsAlmost(0.0))
greenthread.sleep(mox.IsAlmost(0.0))
m.StubOutWithMock(timeutils, 'utcnow')
timeutils.utcnow().AndReturn(now)
timeutils.utcnow().AndReturn(now + second - smidgen)
timeutils.utcnow().AndReturn(now)
timeutils.utcnow().AndReturn(now + second + second)
timeutils.utcnow().AndReturn(now)
timeutils.utcnow().AndReturn(now + second + smidgen)
timeutils.utcnow().AndReturn(now)
m.StubOutWithMock(loopingcall, '_ts')
loopingcall._ts().AndReturn(now)
loopingcall._ts().AndReturn(now + second - smidgen)
loopingcall._ts().AndReturn(now)
loopingcall._ts().AndReturn(now + second + second)
loopingcall._ts().AndReturn(now)
loopingcall._ts().AndReturn(now + second + smidgen)
loopingcall._ts().AndReturn(now)
m.ReplayAll()

timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_zero)
Expand Down

0 comments on commit ab5d5f1

Please sign in to comment.