Revision 3dbe3ddf test/ganeti.locking_unittest.py

b/test/ganeti.locking_unittest.py
612 612

  
613 613
    self.assertRaises(Queue.Empty, self.done.get_nowait)
614 614

  
615
  def testIllegalDowngrade(self):
616
    # Not yet acquired
617
    self.assertRaises(AssertionError, self.sl.downgrade)
618

  
619
    # Acquire in shared mode, downgrade should be no-op
620
    self.assertTrue(self.sl.acquire(shared=1))
621
    self.assertTrue(self.sl._is_owned(shared=1))
622
    self.assertTrue(self.sl.downgrade())
623
    self.assertTrue(self.sl._is_owned(shared=1))
624
    self.sl.release()
625

  
626
  def testDowngrade(self):
627
    self.assertTrue(self.sl.acquire())
628
    self.assertTrue(self.sl._is_owned(shared=0))
629
    self.assertTrue(self.sl.downgrade())
630
    self.assertTrue(self.sl._is_owned(shared=1))
631
    self.sl.release()
632

  
633
  @_Repeat
634
  def testDowngradeJumpsAheadOfExclusive(self):
635
    def _KeepExclusive(ev_got, ev_downgrade, ev_release):
636
      self.assertTrue(self.sl.acquire())
637
      self.assertTrue(self.sl._is_owned(shared=0))
638
      ev_got.set()
639
      ev_downgrade.wait()
640
      self.assertTrue(self.sl._is_owned(shared=0))
641
      self.assertTrue(self.sl.downgrade())
642
      self.assertTrue(self.sl._is_owned(shared=1))
643
      ev_release.wait()
644
      self.assertTrue(self.sl._is_owned(shared=1))
645
      self.sl.release()
646

  
647
    def _KeepExclusive2(ev_started, ev_release):
648
      self.assertTrue(self.sl.acquire(test_notify=ev_started.set))
649
      self.assertTrue(self.sl._is_owned(shared=0))
650
      ev_release.wait()
651
      self.assertTrue(self.sl._is_owned(shared=0))
652
      self.sl.release()
653

  
654
    def _KeepShared(ev_started, ev_got, ev_release):
655
      self.assertTrue(self.sl.acquire(shared=1, test_notify=ev_started.set))
656
      self.assertTrue(self.sl._is_owned(shared=1))
657
      ev_got.set()
658
      ev_release.wait()
659
      self.assertTrue(self.sl._is_owned(shared=1))
660
      self.sl.release()
661

  
662
    # Acquire lock in exclusive mode
663
    ev_got_excl1 = threading.Event()
664
    ev_downgrade_excl1 = threading.Event()
665
    ev_release_excl1 = threading.Event()
666
    th_excl1 = self._addThread(target=_KeepExclusive,
667
                               args=(ev_got_excl1, ev_downgrade_excl1,
668
                                     ev_release_excl1))
669
    ev_got_excl1.wait()
670

  
671
    # Start a second exclusive acquire
672
    ev_started_excl2 = threading.Event()
673
    ev_release_excl2 = threading.Event()
674
    th_excl2 = self._addThread(target=_KeepExclusive2,
675
                               args=(ev_started_excl2, ev_release_excl2))
676
    ev_started_excl2.wait()
677

  
678
    # Start shared acquires, will jump ahead of second exclusive acquire when
679
    # first exclusive acquire downgrades
680
    ev_shared = [(threading.Event(), threading.Event()) for _ in range(5)]
681
    ev_release_shared = threading.Event()
682

  
683
    th_shared = [self._addThread(target=_KeepShared,
684
                                 args=(ev_started, ev_got, ev_release_shared))
685
                 for (ev_started, ev_got) in ev_shared]
686

  
687
    # Wait for all shared acquires to start
688
    for (ev, _) in ev_shared:
689
      ev.wait()
690

  
691
    # Check lock information
692
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER])),
693
                     (self.sl.name, "exclusive", [th_excl1.getName()], None))
694
    (_, _, _, pending) = self.sl.GetInfo(set([query.LQ_PENDING]))
695
    self.assertEqual([(pendmode, sorted(waiting))
696
                      for (pendmode, waiting) in pending],
697
                     [("exclusive", [th_excl2.getName()]),
698
                      ("shared", sorted(th.getName() for th in th_shared))])
699

  
700
    # Shared acquires won't start until the exclusive lock is downgraded
701
    ev_downgrade_excl1.set()
702

  
703
    # Wait for all shared acquires to be successful
704
    for (_, ev) in ev_shared:
705
      ev.wait()
706

  
707
    # Check lock information again
708
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_PENDING])),
709
                     (self.sl.name, "shared", None,
710
                      [("exclusive", [th_excl2.getName()])]))
711
    (_, _, owner, _) = self.sl.GetInfo(set([query.LQ_OWNER]))
712
    self.assertEqual(set(owner), set([th_excl1.getName()] +
713
                                     [th.getName() for th in th_shared]))
714

  
715
    ev_release_excl1.set()
716
    ev_release_excl2.set()
717
    ev_release_shared.set()
718

  
719
    self._waitThreads()
720

  
721
    self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER,
722
                                          query.LQ_PENDING])),
723
                     (self.sl.name, None, None, []))
724

  
615 725
  @_Repeat
616 726
  def testMixedAcquireTimeout(self):
617 727
    sync = threading.Event()
......
1374 1484
    self.assertEqual(self.done.get_nowait(), 'DONE')
1375 1485
    self._setUpLS()
1376 1486

  
1487
  def testAcquireWithNamesDowngrade(self):
1488
    self.assertEquals(self.ls.acquire("two", shared=0), set(["two"]))
1489
    self.assertTrue(self.ls._is_owned())
1490
    self.assertFalse(self.ls._get_lock()._is_owned())
1491
    self.ls.release()
1492
    self.assertFalse(self.ls._is_owned())
1493
    self.assertFalse(self.ls._get_lock()._is_owned())
1494
    # Can't downgrade after releasing
1495
    self.assertRaises(AssertionError, self.ls.downgrade, "two")
1496

  
1497
  def testDowngrade(self):
1498
    # Not owning anything, must raise an exception
1499
    self.assertFalse(self.ls._is_owned())
1500
    self.assertRaises(AssertionError, self.ls.downgrade)
1501

  
1502
    self.assertFalse(compat.any(i._is_owned()
1503
                                for i in self.ls._get_lockdict().values()))
1504

  
1505
    self.assertEquals(self.ls.acquire(None, shared=0),
1506
                      set(["one", "two", "three"]))
1507
    self.assertRaises(AssertionError, self.ls.downgrade, "unknown lock")
1508

  
1509
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1510
    self.assertTrue(compat.all(i._is_owned(shared=0)
1511
                               for i in self.ls._get_lockdict().values()))
1512

  
1513
    # Start downgrading locks
1514
    self.assertTrue(self.ls.downgrade(names=["one"]))
1515
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1516
    self.assertTrue(compat.all(lock._is_owned(shared=[0, 1][int(name == "one")])
1517
                               for name, lock in
1518
                                 self.ls._get_lockdict().items()))
1519

  
1520
    self.assertTrue(self.ls.downgrade(names="two"))
1521
    self.assertTrue(self.ls._get_lock()._is_owned(shared=0))
1522
    should_share = lambda name: [0, 1][int(name in ("one", "two"))]
1523
    self.assertTrue(compat.all(lock._is_owned(shared=should_share(name))
1524
                               for name, lock in
1525
                                 self.ls._get_lockdict().items()))
1526

  
1527
    # Downgrading the last exclusive lock to shared must downgrade the
1528
    # lockset-internal lock too
1529
    self.assertTrue(self.ls.downgrade(names="three"))
1530
    self.assertTrue(self.ls._get_lock()._is_owned(shared=1))
1531
    self.assertTrue(compat.all(i._is_owned(shared=1)
1532
                               for i in self.ls._get_lockdict().values()))
1533

  
1534
    # Downgrading a shared lock must be a no-op
1535
    self.assertTrue(self.ls.downgrade(names=["one", "three"]))
1536
    self.assertTrue(self.ls._get_lock()._is_owned(shared=1))
1537
    self.assertTrue(compat.all(i._is_owned(shared=1)
1538
                               for i in self.ls._get_lockdict().values()))
1539

  
1540
    self.ls.release()
1541

  
1377 1542
  def testPriority(self):
1378 1543
    def _Acquire(prev, next, name, priority, success_fn):
1379 1544
      prev.wait()

Also available in: Unified diff