Allow StackLock to be used as a context manager

We initially didn't implement this class as a context manager because it
was being used exclusively to lock operations that were happening in an
asycnronous thread (hence the thread_lock() context manager). However, we
now have some uses for it in the same thread (see
Ifa48b179723a2100fff548467db9e162bc669d13), so it makes sense to be able to
use the lock object itself as a context manager.

Change-Id: Ib90df8f8a149b57b0588d4fc9951f7f035ad7567
This commit is contained in:
Zane Bitter 2016-01-25 19:55:04 -05:00
parent 62e60c09be
commit 3a204da62d
2 changed files with 34 additions and 0 deletions

View File

@ -124,6 +124,14 @@ class StackLock(object):
"%(stack)s" % {'engine': self.engine_id,
'stack': self.stack_id})
def __enter__(self):
self.acquire()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.release()
return False
@contextlib.contextmanager
def thread_lock(self, retry=True):
"""Acquire a lock and release it only if there is an exception.

View File

@ -161,6 +161,32 @@ class StackLockTest(common.HeatTestCase):
mock_steal.assert_has_calls(
[mock.call(self.stack_id, 'fake-engine-id', self.engine_id)] * 2)
def test_context_mgr_exception(self):
stack_lock_object.StackLock.create = mock.Mock(return_value=None)
stack_lock_object.StackLock.release = mock.Mock(return_value=None)
slock = stack_lock.StackLock(self.context, self.stack_id,
self.engine_id)
def check_lock():
with slock:
self.assertEqual(1,
stack_lock_object.StackLock.create.call_count)
raise self.TestThreadLockException
self.assertRaises(self.TestThreadLockException, check_lock)
self.assertEqual(1, stack_lock_object.StackLock.release.call_count)
def test_context_mgr_noexception(self):
stack_lock_object.StackLock.create = mock.Mock(return_value=None)
stack_lock_object.StackLock.release = mock.Mock(return_value=None)
slock = stack_lock.StackLock(self.context, self.stack_id,
self.engine_id)
with slock:
self.assertEqual(1,
stack_lock_object.StackLock.create.call_count)
self.assertEqual(1, stack_lock_object.StackLock.release.call_count)
def test_thread_lock_context_mgr_exception_acquire_success(self):
stack_lock_object.StackLock.create = mock.Mock(return_value=None)
stack_lock_object.StackLock.release = mock.Mock(return_value=None)