4 # Copyright (C) 2006, 2007 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Script for unittesting the locking module"""
30 from ganeti import locking
31 from ganeti import errors
32 from threading import Thread
35 # This is used to test the ssynchronize decorator.
36 # Since it's passed as input to a decorator it must be declared as a global.
37 _decoratorlock = locking.SharedLock()
40 class TestSharedLock(unittest.TestCase):
41 """SharedLock tests"""
44 self.sl = locking.SharedLock()
45 # helper threads use the 'done' queue to tell the master they finished.
46 self.done = Queue.Queue(0)
48 def testSequenceAndOwnership(self):
49 self.assert_(not self.sl._is_owned())
50 self.sl.acquire(shared=1)
51 self.assert_(self.sl._is_owned())
52 self.assert_(self.sl._is_owned(shared=1))
53 self.assert_(not self.sl._is_owned(shared=0))
55 self.assert_(not self.sl._is_owned())
57 self.assert_(self.sl._is_owned())
58 self.assert_(not self.sl._is_owned(shared=1))
59 self.assert_(self.sl._is_owned(shared=0))
61 self.assert_(not self.sl._is_owned())
62 self.sl.acquire(shared=1)
63 self.assert_(self.sl._is_owned())
64 self.assert_(self.sl._is_owned(shared=1))
65 self.assert_(not self.sl._is_owned(shared=0))
67 self.assert_(not self.sl._is_owned())
69 def testBooleanValue(self):
70 # semaphores are supposed to return a true value on a successful acquire
71 self.assert_(self.sl.acquire(shared=1))
73 self.assert_(self.sl.acquire())
76 def testDoubleLockingStoE(self):
77 self.sl.acquire(shared=1)
78 self.assertRaises(AssertionError, self.sl.acquire)
80 def testDoubleLockingEtoS(self):
82 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
84 def testDoubleLockingStoS(self):
85 self.sl.acquire(shared=1)
86 self.assertRaises(AssertionError, self.sl.acquire, shared=1)
88 def testDoubleLockingEtoE(self):
90 self.assertRaises(AssertionError, self.sl.acquire)
92 # helper functions: called in a separate thread they acquire the lock, send
93 # their identifier on the done queue, then release it.
94 def _doItSharer(self):
96 self.sl.acquire(shared=1)
99 except errors.LockError:
102 def _doItExclusive(self):
107 except errors.LockError:
110 def _doItDelete(self):
114 except errors.LockError:
117 def testSharersCanCoexist(self):
118 self.sl.acquire(shared=1)
119 Thread(target=self._doItSharer).start()
120 self.assert_(self.done.get(True, 1))
123 def testExclusiveBlocksExclusive(self):
125 Thread(target=self._doItExclusive).start()
126 # give it a bit of time to check that it's not actually doing anything
127 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
129 self.assert_(self.done.get(True, 1))
131 def testExclusiveBlocksDelete(self):
133 Thread(target=self._doItDelete).start()
134 # give it a bit of time to check that it's not actually doing anything
135 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
137 self.assert_(self.done.get(True, 1))
139 def testExclusiveBlocksSharer(self):
141 Thread(target=self._doItSharer).start()
143 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
145 self.assert_(self.done.get(True, 1))
147 def testSharerBlocksExclusive(self):
148 self.sl.acquire(shared=1)
149 Thread(target=self._doItExclusive).start()
151 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
153 self.assert_(self.done.get(True, 1))
155 def testSharerBlocksDelete(self):
156 self.sl.acquire(shared=1)
157 Thread(target=self._doItDelete).start()
159 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
161 self.assert_(self.done.get(True, 1))
163 def testWaitingExclusiveBlocksSharer(self):
164 self.sl.acquire(shared=1)
165 # the lock is acquired in shared mode...
166 Thread(target=self._doItExclusive).start()
167 # ...but now an exclusive is waiting...
169 Thread(target=self._doItSharer).start()
170 # ...so the sharer should be blocked as well
171 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
173 # The exclusive passed before
174 self.assertEqual(self.done.get(True, 1), 'EXC')
175 self.assertEqual(self.done.get(True, 1), 'SHR')
177 def testWaitingSharerBlocksExclusive(self):
179 # the lock is acquired in exclusive mode...
180 Thread(target=self._doItSharer).start()
181 # ...but now a sharer is waiting...
183 Thread(target=self._doItExclusive).start()
184 # ...the exclusive is waiting too...
185 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
187 # The sharer passed before
188 self.assertEqual(self.done.get(True, 1), 'SHR')
189 self.assertEqual(self.done.get(True, 1), 'EXC')
191 def testNoNonBlocking(self):
192 self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
193 self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
195 self.sl.delete(blocking=0) # Fine, because the lock is already acquired
197 def testDelete(self):
199 self.assertRaises(errors.LockError, self.sl.acquire)
200 self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
201 self.assertRaises(errors.LockError, self.sl.delete)
203 def testNoDeleteIfSharer(self):
204 self.sl.acquire(shared=1)
205 self.assertRaises(AssertionError, self.sl.delete)
207 def testDeletePendingSharersExclusiveDelete(self):
209 Thread(target=self._doItSharer).start()
210 Thread(target=self._doItSharer).start()
212 Thread(target=self._doItExclusive).start()
213 Thread(target=self._doItDelete).start()
216 # The two threads who were pending return both ERR
217 self.assertEqual(self.done.get(True, 1), 'ERR')
218 self.assertEqual(self.done.get(True, 1), 'ERR')
219 self.assertEqual(self.done.get(True, 1), 'ERR')
220 self.assertEqual(self.done.get(True, 1), 'ERR')
222 def testDeletePendingDeleteExclusiveSharers(self):
224 Thread(target=self._doItDelete).start()
225 Thread(target=self._doItExclusive).start()
227 Thread(target=self._doItSharer).start()
228 Thread(target=self._doItSharer).start()
231 # The two threads who were pending return both ERR
232 self.assertEqual(self.done.get(True, 1), 'ERR')
233 self.assertEqual(self.done.get(True, 1), 'ERR')
234 self.assertEqual(self.done.get(True, 1), 'ERR')
235 self.assertEqual(self.done.get(True, 1), 'ERR')
238 class TestSSynchronizedDecorator(unittest.TestCase):
239 """Shared Lock Synchronized decorator test"""
242 # helper threads use the 'done' queue to tell the master they finished.
243 self.done = Queue.Queue(0)
245 @locking.ssynchronized(_decoratorlock)
246 def _doItExclusive(self):
247 self.assert_(_decoratorlock._is_owned())
250 @locking.ssynchronized(_decoratorlock, shared=1)
251 def _doItSharer(self):
252 self.assert_(_decoratorlock._is_owned(shared=1))
255 def testDecoratedFunctions(self):
256 self._doItExclusive()
257 self.assert_(not _decoratorlock._is_owned())
259 self.assert_(not _decoratorlock._is_owned())
261 def testSharersCanCoexist(self):
262 _decoratorlock.acquire(shared=1)
263 Thread(target=self._doItSharer).start()
264 self.assert_(self.done.get(True, 1))
265 _decoratorlock.release()
267 def testExclusiveBlocksExclusive(self):
268 _decoratorlock.acquire()
269 Thread(target=self._doItExclusive).start()
270 # give it a bit of time to check that it's not actually doing anything
271 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
272 _decoratorlock.release()
273 self.assert_(self.done.get(True, 1))
275 def testExclusiveBlocksSharer(self):
276 _decoratorlock.acquire()
277 Thread(target=self._doItSharer).start()
279 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
280 _decoratorlock.release()
281 self.assert_(self.done.get(True, 1))
283 def testSharerBlocksExclusive(self):
284 _decoratorlock.acquire(shared=1)
285 Thread(target=self._doItExclusive).start()
287 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
288 _decoratorlock.release()
289 self.assert_(self.done.get(True, 1))
292 class TestLockSet(unittest.TestCase):
296 self.resources = ['one', 'two', 'three']
297 self.ls = locking.LockSet(members=self.resources)
298 # helper threads use the 'done' queue to tell the master they finished.
299 self.done = Queue.Queue(0)
301 def testResources(self):
302 self.assertEquals(self.ls._names(), set(self.resources))
303 newls = locking.LockSet()
304 self.assertEquals(newls._names(), set())
306 def testAcquireRelease(self):
307 self.assert_(self.ls.acquire('one'))
308 self.assertEquals(self.ls._list_owned(), set(['one']))
310 self.assertEquals(self.ls._list_owned(), set())
311 self.assertEquals(self.ls.acquire(['one']), set(['one']))
312 self.assertEquals(self.ls._list_owned(), set(['one']))
314 self.assertEquals(self.ls._list_owned(), set())
315 self.ls.acquire(['one', 'two', 'three'])
316 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
317 self.ls.release('one')
318 self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
319 self.ls.release(['three'])
320 self.assertEquals(self.ls._list_owned(), set(['two']))
322 self.assertEquals(self.ls._list_owned(), set())
323 self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
324 self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
326 self.assertEquals(self.ls._list_owned(), set())
328 def testNoDoubleAcquire(self):
329 self.ls.acquire('one')
330 self.assertRaises(AssertionError, self.ls.acquire, 'one')
331 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
332 self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
334 self.ls.acquire(['one', 'three'])
335 self.ls.release('one')
336 self.assertRaises(AssertionError, self.ls.acquire, ['two'])
337 self.ls.release('three')
339 def testNoWrongRelease(self):
340 self.assertRaises(AssertionError, self.ls.release)
341 self.ls.acquire('one')
342 self.assertRaises(AssertionError, self.ls.release, 'two')
344 def testAddRemove(self):
346 self.assertEquals(self.ls._list_owned(), set())
347 self.assert_('four' in self.ls._names())
348 self.ls.add(['five', 'six', 'seven'], acquired=1)
349 self.assert_('five' in self.ls._names())
350 self.assert_('six' in self.ls._names())
351 self.assert_('seven' in self.ls._names())
352 self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
353 self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
354 self.assert_('five' not in self.ls._names())
355 self.assert_('six' not in self.ls._names())
356 self.assertEquals(self.ls._list_owned(), set(['seven']))
357 self.ls.add('eight', acquired=1, shared=1)
358 self.assert_('eight' in self.ls._names())
359 self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
360 self.ls.remove('seven')
361 self.assert_('seven' not in self.ls._names())
362 self.assertEquals(self.ls._list_owned(), set(['eight']))
364 self.ls.remove(['two'])
365 self.assert_('two' not in self.ls._names())
366 self.ls.acquire('three')
367 self.assertEquals(self.ls.remove(['three']), ['three'])
368 self.assert_('three' not in self.ls._names())
369 self.assertEquals(self.ls.remove('three'), [])
370 self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
371 self.assert_('one' not in self.ls._names())
373 def testRemoveNonBlocking(self):
374 self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
375 self.ls.acquire('one')
376 self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
377 self.ls.acquire(['two', 'three'])
378 self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
381 def testNoDoubleAdd(self):
382 self.assertRaises(errors.LockError, self.ls.add, 'two')
384 self.assertRaises(errors.LockError, self.ls.add, 'four')
386 def testNoWrongRemoves(self):
387 self.ls.acquire(['one', 'three'], shared=1)
388 # Cannot remove 'two' while holding something which is not a superset
389 self.assertRaises(AssertionError, self.ls.remove, 'two')
390 # Cannot remove 'three' as we are sharing it
391 self.assertRaises(AssertionError, self.ls.remove, 'three')
393 def testAcquireSetLock(self):
394 # acquire the set-lock exclusively
395 self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
396 self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
397 self.assertEquals(self.ls._is_owned(), True)
398 self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
399 # I can still add/remove elements...
400 self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
401 self.assert_(self.ls.add('six'))
404 self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
405 # adding new elements is not possible
406 self.assertRaises(AssertionError, self.ls.add, 'five')
409 def testAcquireWithRepetitions(self):
410 self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
411 set(['two', 'two', 'three']))
412 self.ls.release(['two', 'two'])
413 self.assertEquals(self.ls._list_owned(), set(['three']))
415 def testEmptyAcquire(self):
416 # Acquire an empty list of locks...
417 self.assertEquals(self.ls.acquire([]), set())
418 self.assertEquals(self.ls._list_owned(), set())
419 # New locks can still be addded
420 self.assert_(self.ls.add('six'))
421 # "re-acquiring" is not an issue, since we had really acquired nothing
422 self.assertEquals(self.ls.acquire([], shared=1), set())
423 self.assertEquals(self.ls._list_owned(), set())
424 # We haven't really acquired anything, so we cannot release
425 self.assertRaises(AssertionError, self.ls.release)
427 def _doLockSet(self, set, shared):
429 self.ls.acquire(set, shared=shared)
430 self.done.put('DONE')
432 except errors.LockError:
435 def _doAddSet(self, set):
437 self.ls.add(set, acquired=1)
438 self.done.put('DONE')
440 except errors.LockError:
443 def _doRemoveSet(self, set):
444 self.done.put(self.ls.remove(set))
446 def testConcurrentSharedAcquire(self):
447 self.ls.acquire(['one', 'two'], shared=1)
448 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
449 self.assertEqual(self.done.get(True, 1), 'DONE')
450 Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
451 self.assertEqual(self.done.get(True, 1), 'DONE')
452 Thread(target=self._doLockSet, args=('three', 1)).start()
453 self.assertEqual(self.done.get(True, 1), 'DONE')
454 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
455 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
456 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
458 self.assertEqual(self.done.get(True, 1), 'DONE')
459 self.assertEqual(self.done.get(True, 1), 'DONE')
461 def testConcurrentExclusiveAcquire(self):
462 self.ls.acquire(['one', 'two'])
463 Thread(target=self._doLockSet, args=('three', 1)).start()
464 self.assertEqual(self.done.get(True, 1), 'DONE')
465 Thread(target=self._doLockSet, args=('three', 0)).start()
466 self.assertEqual(self.done.get(True, 1), 'DONE')
467 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
468 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
469 Thread(target=self._doLockSet, args=('one', 0)).start()
470 Thread(target=self._doLockSet, args=('one', 1)).start()
471 Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
472 Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
473 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
475 self.assertEqual(self.done.get(True, 1), 'DONE')
476 self.assertEqual(self.done.get(True, 1), 'DONE')
477 self.assertEqual(self.done.get(True, 1), 'DONE')
478 self.assertEqual(self.done.get(True, 1), 'DONE')
479 self.assertEqual(self.done.get(True, 1), 'DONE')
480 self.assertEqual(self.done.get(True, 1), 'DONE')
482 def testConcurrentRemove(self):
484 self.ls.acquire(['one', 'two', 'four'])
485 Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
486 Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
487 Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
488 Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
489 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
490 self.ls.remove('one')
492 self.assertEqual(self.done.get(True, 1), 'ERR')
493 self.assertEqual(self.done.get(True, 1), 'ERR')
494 self.assertEqual(self.done.get(True, 1), 'ERR')
495 self.assertEqual(self.done.get(True, 1), 'ERR')
496 self.ls.add(['five', 'six'], acquired=1)
497 Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
498 Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
499 Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
500 Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
501 self.ls.remove('five')
503 self.assertEqual(self.done.get(True, 1), 'DONE')
504 self.assertEqual(self.done.get(True, 1), 'DONE')
505 self.assertEqual(self.done.get(True, 1), 'DONE')
506 self.assertEqual(self.done.get(True, 1), 'DONE')
507 self.ls.acquire(['three', 'four'])
508 Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
509 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
510 self.ls.remove('four')
511 self.assertEqual(self.done.get(True, 1), ['six'])
512 Thread(target=self._doRemoveSet, args=(['two'])).start()
513 self.assertEqual(self.done.get(True, 1), ['two'])
516 def testConcurrentSharedSetLock(self):
517 # share the set-lock...
518 self.ls.acquire(None, shared=1)
519 # ...another thread can share it too
520 Thread(target=self._doLockSet, args=(None, 1)).start()
521 self.assertEqual(self.done.get(True, 1), 'DONE')
522 # ...or just share some elements
523 Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
524 self.assertEqual(self.done.get(True, 1), 'DONE')
525 # ...but not add new ones or remove any
526 Thread(target=self._doAddSet, args=(['nine'])).start()
527 Thread(target=self._doRemoveSet, args=(['two'], )).start()
528 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
529 # this just releases the set-lock
531 self.assertEqual(self.done.get(True, 1), 'DONE')
532 # release the lock on the actual elements so remove() can proceed too
534 self.assertEqual(self.done.get(True, 1), ['two'])
536 def testConcurrentExclusiveSetLock(self):
537 # acquire the set-lock...
538 self.ls.acquire(None, shared=0)
539 # ...no one can do anything else
540 Thread(target=self._doLockSet, args=(None, 1)).start()
541 Thread(target=self._doLockSet, args=(None, 0)).start()
542 Thread(target=self._doLockSet, args=(['three'], 0)).start()
543 Thread(target=self._doLockSet, args=(['two'], 1)).start()
544 Thread(target=self._doAddSet, args=(['nine'])).start()
545 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
547 self.assertEqual(self.done.get(True, 1), 'DONE')
548 self.assertEqual(self.done.get(True, 1), 'DONE')
549 self.assertEqual(self.done.get(True, 1), 'DONE')
550 self.assertEqual(self.done.get(True, 1), 'DONE')
551 self.assertEqual(self.done.get(True, 1), 'DONE')
553 def testEmptyLockSet(self):
555 self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
557 self.ls.remove(['one', 'two', 'three'])
558 # and adds/locks by another thread still wait
559 Thread(target=self._doAddSet, args=(['nine'])).start()
560 Thread(target=self._doLockSet, args=(None, 1)).start()
561 Thread(target=self._doLockSet, args=(None, 0)).start()
562 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
564 self.assertEqual(self.done.get(True, 1), 'DONE')
565 self.assertEqual(self.done.get(True, 1), 'DONE')
566 self.assertEqual(self.done.get(True, 1), 'DONE')
568 self.assertEqual(self.ls.remove(['nine']), ['nine'])
570 self.assertEqual(self.ls.acquire(None, shared=1), set())
571 # other sharers can go, adds still wait
572 Thread(target=self._doLockSet, args=(None, 1)).start()
573 self.assertEqual(self.done.get(True, 1), 'DONE')
574 Thread(target=self._doAddSet, args=(['nine'])).start()
575 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
577 self.assertEqual(self.done.get(True, 1), 'DONE')
580 class TestGanetiLockManager(unittest.TestCase):
583 self.nodes=['n1', 'n2']
584 self.instances=['i1', 'i2', 'i3']
585 self.GL = locking.GanetiLockManager(nodes=self.nodes,
586 instances=self.instances)
587 self.done = Queue.Queue(0)
590 # Don't try this at home...
591 locking.GanetiLockManager._instance = None
593 def testLockingConstants(self):
594 # The locking library internally cheats by assuming its constants have some
595 # relationships with each other. Check those hold true.
596 # This relationship is also used in the Processor to recursively acquire
597 # the right locks. Again, please don't break it.
598 for i in range(len(locking.LEVELS)):
599 self.assertEqual(i, locking.LEVELS[i])
601 def testDoubleGLFails(self):
602 self.assertRaises(AssertionError, locking.GanetiLockManager)
604 def testLockNames(self):
605 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
606 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
607 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
610 def testInitAndResources(self):
611 locking.GanetiLockManager._instance = None
612 self.GL = locking.GanetiLockManager()
613 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
614 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
615 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
617 locking.GanetiLockManager._instance = None
618 self.GL = locking.GanetiLockManager(nodes=self.nodes)
619 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
620 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
621 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
623 locking.GanetiLockManager._instance = None
624 self.GL = locking.GanetiLockManager(instances=self.instances)
625 self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
626 self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
627 self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
630 def testAcquireRelease(self):
631 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
632 self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
633 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
634 self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
635 self.GL.release(locking.LEVEL_NODE, ['n2'])
636 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
637 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
638 self.GL.release(locking.LEVEL_NODE)
639 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
640 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
641 self.GL.release(locking.LEVEL_INSTANCE)
642 self.assertRaises(errors.LockError, self.GL.acquire,
643 locking.LEVEL_INSTANCE, ['i5'])
644 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
645 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
647 def testAcquireWholeSets(self):
648 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
649 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
651 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
653 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
655 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
657 self.GL.release(locking.LEVEL_NODE)
658 self.GL.release(locking.LEVEL_INSTANCE)
659 self.GL.release(locking.LEVEL_CLUSTER)
661 def testAcquireWholeAndPartial(self):
662 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
663 self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
665 self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
667 self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
669 self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
671 self.GL.release(locking.LEVEL_NODE)
672 self.GL.release(locking.LEVEL_INSTANCE)
673 self.GL.release(locking.LEVEL_CLUSTER)
675 def testBGLDependency(self):
676 self.assertRaises(AssertionError, self.GL.acquire,
677 locking.LEVEL_NODE, ['n1', 'n2'])
678 self.assertRaises(AssertionError, self.GL.acquire,
679 locking.LEVEL_INSTANCE, ['i3'])
680 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
681 self.GL.acquire(locking.LEVEL_NODE, ['n1'])
682 self.assertRaises(AssertionError, self.GL.release,
683 locking.LEVEL_CLUSTER, ['BGL'])
684 self.assertRaises(AssertionError, self.GL.release,
685 locking.LEVEL_CLUSTER)
686 self.GL.release(locking.LEVEL_NODE)
687 self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
688 self.assertRaises(AssertionError, self.GL.release,
689 locking.LEVEL_CLUSTER, ['BGL'])
690 self.assertRaises(AssertionError, self.GL.release,
691 locking.LEVEL_CLUSTER)
692 self.GL.release(locking.LEVEL_INSTANCE)
694 def testWrongOrder(self):
695 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
696 self.GL.acquire(locking.LEVEL_NODE, ['n2'])
697 self.assertRaises(AssertionError, self.GL.acquire,
698 locking.LEVEL_NODE, ['n1'])
699 self.assertRaises(AssertionError, self.GL.acquire,
700 locking.LEVEL_INSTANCE, ['i2'])
702 # Helper function to run as a thread that shared the BGL and then acquires
703 # some locks at another level.
704 def _doLock(self, level, names, shared):
706 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
707 self.GL.acquire(level, names, shared=shared)
708 self.done.put('DONE')
709 self.GL.release(level)
710 self.GL.release(locking.LEVEL_CLUSTER)
711 except errors.LockError:
714 def testConcurrency(self):
715 self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
716 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
717 self.assertEqual(self.done.get(True, 1), 'DONE')
718 self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
719 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
720 self.assertEqual(self.done.get(True, 1), 'DONE')
721 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
722 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
723 self.GL.release(locking.LEVEL_INSTANCE)
724 self.assertEqual(self.done.get(True, 1), 'DONE')
725 self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
726 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
727 self.assertEqual(self.done.get(True, 1), 'DONE')
728 Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
729 self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
730 self.GL.release(locking.LEVEL_INSTANCE)
731 self.assertEqual(self.done.get(True, 1), 'DONE')
734 if __name__ == '__main__':
736 #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
737 #unittest.TextTestRunner(verbosity=2).run(suite)