From a6db1af243bc10992554d362587b389e88d332d3 Mon Sep 17 00:00:00 2001
From: Michael Hanselmann <hansmi@google.com>
Date: Thu, 15 Oct 2009 14:39:14 +0200
Subject: [PATCH] mcpu: Use new timeout class for timeout

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
---
 lib/mcpu.py                  | 39 ++++++++++++++++--------------------
 test/ganeti.mcpu_unittest.py |  7 +++++--
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/lib/mcpu.py b/lib/mcpu.py
index d53bd58f1..4e096d1d5 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 f7d8e0e56..a60ebac21 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__":
-- 
GitLab