Commit a7770f03 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

mcpu: Adjust lock acquire strategy



The changes to job queue processing require some changes on this class'
interface. LockAttemptTimeoutStrategy might move to another place, but that'll
be done in a later patch.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarRené Nussbaumer <rn@google.com>
parent 831bbbc1
......@@ -71,60 +71,40 @@ def _CalculateLockAttemptTimeouts():
return result
class _LockAttemptTimeoutStrategy(object):
class LockAttemptTimeoutStrategy(object):
"""Class with lock acquire timeout strategy.
"""
__slots__ = [
"_attempt",
"_timeouts",
"_random_fn",
"_start_time",
"_time_fn",
"_running_timeout",
]
_TIMEOUT_PER_ATTEMPT = _CalculateLockAttemptTimeouts()
def __init__(self, attempt=0, _time_fn=time.time, _random_fn=random.random):
def __init__(self, _time_fn=time.time, _random_fn=random.random):
"""Initializes this class.
@type attempt: int
@param attempt: Current attempt number
@param _time_fn: Time function for unittests
@param _random_fn: Random number generator for unittests
"""
object.__init__(self)
if attempt < 0:
raise ValueError("Attempt must be zero or positive")
self._attempt = attempt
self._timeouts = iter(self._TIMEOUT_PER_ATTEMPT)
self._time_fn = _time_fn
self._random_fn = _random_fn
try:
timeout = self._TIMEOUT_PER_ATTEMPT[attempt]
except IndexError:
# No more timeouts, do blocking acquire
timeout = None
self._running_timeout = locking.RunningTimeout(timeout, False,
_time_fn=_time_fn)
def NextAttempt(self):
"""Returns the strategy for the next attempt.
"""Returns the timeout for the next attempt.
"""
return _LockAttemptTimeoutStrategy(attempt=self._attempt + 1,
_time_fn=self._time_fn,
_random_fn=self._random_fn)
def CalcRemainingTimeout(self):
"""Returns the remaining timeout.
"""
timeout = self._running_timeout.Remaining()
try:
timeout = self._timeouts.next()
except StopIteration:
# No more timeouts, do blocking acquire
timeout = None
if timeout is not None:
# Add a small variation (-/+ 5%) to timeout. This helps in situations
......
......@@ -31,32 +31,27 @@ import testutils
class TestLockAttemptTimeoutStrategy(unittest.TestCase):
def testConstants(self):
tpa = mcpu._LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT
tpa = mcpu.LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT
self.assert_(len(tpa) > 10)
self.assert_(sum(tpa) >= 150.0)
def testSimple(self):
strat = mcpu._LockAttemptTimeoutStrategy(_random_fn=lambda: 0.5,
_time_fn=lambda: 0.0)
self.assertEqual(strat._attempt, 0)
strat = mcpu.LockAttemptTimeoutStrategy(_random_fn=lambda: 0.5,
_time_fn=lambda: 0.0)
prev = None
for i in range(len(mcpu._LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT)):
timeout = strat.CalcRemainingTimeout()
for i in range(len(strat._TIMEOUT_PER_ATTEMPT)):
timeout = strat.NextAttempt()
self.assert_(timeout is not None)
self.assert_(timeout <= 10.0)
self.assert_(timeout >= 0.0)
self.assert_(prev is None or timeout >= prev)
strat = strat.NextAttempt()
self.assertEqual(strat._attempt, i + 1)
prev = timeout
for _ in range(10):
self.assert_(strat.CalcRemainingTimeout() is None)
self.assert_(strat.NextAttempt() is None)
if __name__ == "__main__":
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment