diff --git a/lib/mcpu.py b/lib/mcpu.py index d53bd58f11461e84d9f06ca17b4b2ba9d00ecb8b..4e096d1d52f8dfa0b5e8e7bfd661b494d2e74cd2 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -81,6 +81,7 @@ class _LockAttemptTimeoutStrategy(object): "_random_fn", "_start_time", "_time_fn", + "_running_timeout", ] _TIMEOUT_PER_ATTEMPT = _CalculateLockAttemptTimeouts() @@ -103,7 +104,14 @@ class _LockAttemptTimeoutStrategy(object): self._time_fn = _time_fn self._random_fn = _random_fn - self._start_time = None + 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. @@ -117,29 +125,16 @@ class _LockAttemptTimeoutStrategy(object): """Returns the remaining timeout. """ - try: - timeout = self._TIMEOUT_PER_ATTEMPT[self._attempt] - except IndexError: - # No more timeouts, do blocking acquire - return None - - # Get start time on first calculation - if self._start_time is None: - self._start_time = self._time_fn() - - # Calculate remaining time for this attempt - remaining_timeout = self._start_time + timeout - self._time_fn() - - # Add a small variation (-/+ 5%) to timeouts. This helps in situations - # where two or more jobs are fighting for the same lock(s). - variation_range = remaining_timeout * 0.1 - remaining_timeout += ((self._random_fn() * variation_range) - - (variation_range * 0.5)) + timeout = self._running_timeout.Remaining() - # Make sure timeout is >= 0 - remaining_timeout = max(0.0, remaining_timeout) + if timeout is not None: + # Add a small variation (-/+ 5%) to timeout. This helps in situations + # where two or more jobs are fighting for the same lock(s). + variation_range = timeout * 0.1 + timeout += ((self._random_fn() * variation_range) - + (variation_range * 0.5)) - return remaining_timeout + return timeout class OpExecCbBase: diff --git a/test/ganeti.mcpu_unittest.py b/test/ganeti.mcpu_unittest.py index f7d8e0e56f95b86d57d3111130f042dd468b8a2e..a60ebac21e74753eadb464691c2c8b0bef03740e 100755 --- a/test/ganeti.mcpu_unittest.py +++ b/test/ganeti.mcpu_unittest.py @@ -40,18 +40,21 @@ class TestLockAttemptTimeoutStrategy(unittest.TestCase): self.assertEqual(strat._attempt, 0) prev = None - for _ in range(len(mcpu._LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT)): + for i in range(len(mcpu._LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT)): timeout = strat.CalcRemainingTimeout() 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 - self.assert_(strat.CalcRemainingTimeout() is None) + for _ in range(10): + self.assert_(strat.CalcRemainingTimeout() is None) if __name__ == "__main__":