Sleep for longer at a time in lock_path.

When lock_path is called and the lock goes for the whole 10 seconds,
the flock is called 1000 times. With this patch, the short 0.01 sleep
is used for the first 1% of the total lock time and then 1% of the
total lock time is used.

Change-Id: Ibed6bdb49bddcdb868742c41f86d2482a7edfd29
This commit is contained in:
David Goetz 2014-08-11 09:43:13 -07:00
parent 698919e67b
commit a0e0014159
2 changed files with 32 additions and 1 deletions
swift/common
test/unit/common

@ -1600,6 +1600,10 @@ def lock_path(directory, timeout=10, timeout_class=None):
mkdirs(directory)
lockpath = '%s/.lock' % directory
fd = os.open(lockpath, os.O_WRONLY | os.O_CREAT)
sleep_time = 0.01
slower_sleep_time = max(timeout * 0.01, sleep_time)
slowdown_at = timeout * 0.01
time_slept = 0
try:
with timeout_class(timeout, lockpath):
while True:
@ -1609,7 +1613,10 @@ def lock_path(directory, timeout=10, timeout_class=None):
except IOError as err:
if err.errno != errno.EAGAIN:
raise
sleep(0.01)
if time_slept > slowdown_at:
sleep_time = slower_sleep_time
sleep(sleep_time)
time_slept += sleep_time
yield True
finally:
os.close(fd)

@ -727,6 +727,30 @@ class TestUtils(unittest.TestCase):
finally:
shutil.rmtree(tmpdir)
def test_lock_path_num_sleeps(self):
tmpdir = mkdtemp()
num_short_calls = [0]
exception_raised = [False]
def my_sleep(to_sleep):
if to_sleep == 0.01:
num_short_calls[0] += 1
else:
raise Exception('sleep time changed: %s' % to_sleep)
try:
with mock.patch('swift.common.utils.sleep', my_sleep):
with utils.lock_path(tmpdir):
with utils.lock_path(tmpdir):
pass
except Exception as e:
exception_raised[0] = True
self.assertTrue('sleep time changed' in str(e))
finally:
shutil.rmtree(tmpdir)
self.assertEqual(num_short_calls[0], 11)
self.assertTrue(exception_raised[0])
def test_lock_path_class(self):
tmpdir = mkdtemp()
try: