Revision c6a622cf

b/lib/locking.py
943 943
    return self.__lockdict
944 944

  
945 945
  def is_owned(self):
946
    """Is the current thread a current level owner?"""
946
    """Is the current thread a current level owner?
947

  
948
    @note: Use L{check_owned} to check if a specific lock is held
949

  
950
    """
947 951
    return threading.currentThread() in self.__owners
948 952

  
953
  def check_owned(self, names, shared=-1):
954
    """Check if locks are owned in a specific mode.
955

  
956
    @type names: sequence or string
957
    @param names: Lock names (or a single lock name)
958
    @param shared: See L{SharedLock.is_owned}
959
    @rtype: bool
960
    @note: Use L{is_owned} to check if the current thread holds I{any} lock and
961
      L{list_owned} to get the names of all owned locks
962

  
963
    """
964
    if isinstance(names, basestring):
965
      names = [names]
966

  
967
    # Avoid check if no locks are owned anyway
968
    if names and self.is_owned():
969
      candidates = []
970

  
971
      # Gather references to all locks (in case they're deleted in the meantime)
972
      for lname in names:
973
        try:
974
          lock = self.__lockdict[lname]
975
        except KeyError:
976
          raise errors.LockError("Non-existing lock '%s' in set '%s' (it may"
977
                                 " have been removed)" % (lname, self.name))
978
        else:
979
          candidates.append(lock)
980

  
981
      return compat.all(lock.is_owned(shared=shared) for lock in candidates)
982
    else:
983
      return False
984

  
949 985
  def _add_owned(self, name=None):
950 986
    """Note the current thread owns the given lock"""
951 987
    if name is None:
......
1512 1548
    """
1513 1549
    return self.__keyring[level].list_owned()
1514 1550

  
1551
  def check_owned(self, level, names, shared=-1):
1552
    """Check if locks at a certain level are owned in a specific mode.
1553

  
1554
    @see: L{LockSet.check_owned}
1555

  
1556
    """
1557
    return self.__keyring[level].check_owned(names, shared=shared)
1558

  
1515 1559
  def _upper_owned(self, level):
1516 1560
    """Check that we don't own any lock at a level greater than the given one.
1517 1561

  
b/test/ganeti.locking_unittest.py
1035 1035
    newls = locking.LockSet([], "TestLockSet.testResources")
1036 1036
    self.assertEquals(newls._names(), set())
1037 1037

  
1038
  def testCheckOwnedUnknown(self):
1039
    self.assertFalse(self.ls.check_owned("certainly-not-owning-this-one"))
1040
    for shared in [-1, 0, 1, 6378, 24255]:
1041
      self.assertFalse(self.ls.check_owned("certainly-not-owning-this-one",
1042
                                           shared=shared))
1043

  
1044
  def testCheckOwnedUnknownWhileHolding(self):
1045
    self.assertFalse(self.ls.check_owned([]))
1046
    self.ls.acquire("one", shared=1)
1047
    self.assertRaises(errors.LockError, self.ls.check_owned, "nonexist")
1048
    self.assertTrue(self.ls.check_owned("one", shared=1))
1049
    self.assertFalse(self.ls.check_owned("one", shared=0))
1050
    self.assertFalse(self.ls.check_owned(["one", "two"]))
1051
    self.assertRaises(errors.LockError, self.ls.check_owned,
1052
                      ["one", "nonexist"])
1053
    self.assertRaises(errors.LockError, self.ls.check_owned, "")
1054
    self.ls.release()
1055
    self.assertFalse(self.ls.check_owned([]))
1056
    self.assertFalse(self.ls.check_owned("one"))
1057

  
1038 1058
  def testAcquireRelease(self):
1059
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1039 1060
    self.assert_(self.ls.acquire('one'))
1040 1061
    self.assertEquals(self.ls.list_owned(), set(['one']))
1062
    self.assertTrue(self.ls.check_owned("one"))
1063
    self.assertTrue(self.ls.check_owned("one", shared=0))
1064
    self.assertFalse(self.ls.check_owned("one", shared=1))
1041 1065
    self.ls.release()
1042 1066
    self.assertEquals(self.ls.list_owned(), set())
1067
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1043 1068
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
1044 1069
    self.assertEquals(self.ls.list_owned(), set(['one']))
1045 1070
    self.ls.release()
1046 1071
    self.assertEquals(self.ls.list_owned(), set())
1047 1072
    self.ls.acquire(['one', 'two', 'three'])
1048 1073
    self.assertEquals(self.ls.list_owned(), set(['one', 'two', 'three']))
1074
    self.assertTrue(self.ls.check_owned(self.ls._names()))
1075
    self.assertTrue(self.ls.check_owned(self.ls._names(), shared=0))
1076
    self.assertFalse(self.ls.check_owned(self.ls._names(), shared=1))
1049 1077
    self.ls.release('one')
1078
    self.assertFalse(self.ls.check_owned(["one"]))
1079
    self.assertTrue(self.ls.check_owned(["two", "three"]))
1080
    self.assertTrue(self.ls.check_owned(["two", "three"], shared=0))
1081
    self.assertFalse(self.ls.check_owned(["two", "three"], shared=1))
1050 1082
    self.assertEquals(self.ls.list_owned(), set(['two', 'three']))
1051 1083
    self.ls.release(['three'])
1052 1084
    self.assertEquals(self.ls.list_owned(), set(['two']))
......
1056 1088
    self.assertEquals(self.ls.list_owned(), set(['one', 'three']))
1057 1089
    self.ls.release()
1058 1090
    self.assertEquals(self.ls.list_owned(), set())
1091
    for name in self.ls._names():
1092
      self.assertFalse(self.ls.check_owned(name))
1059 1093

  
1060 1094
  def testNoDoubleAcquire(self):
1061 1095
    self.ls.acquire('one')
......
1504 1538

  
1505 1539
    self.assertFalse(compat.any(i.is_owned()
1506 1540
                                for i in self.ls._get_lockdict().values()))
1541
    self.assertFalse(self.ls.check_owned(self.ls._names()))
1542
    for name in self.ls._names():
1543
      self.assertFalse(self.ls.check_owned(name))
1507 1544

  
1508 1545
    self.assertEquals(self.ls.acquire(None, shared=0),
1509 1546
                      set(["one", "two", "three"]))
1510 1547
    self.assertRaises(AssertionError, self.ls.downgrade, "unknown lock")
1511 1548

  
1549
    self.assertTrue(self.ls.check_owned(self.ls._names(), shared=0))
1550
    for name in self.ls._names():
1551
      self.assertTrue(self.ls.check_owned(name))
1552
      self.assertTrue(self.ls.check_owned(name, shared=0))
1553
      self.assertFalse(self.ls.check_owned(name, shared=1))
1554

  
1512 1555
    self.assertTrue(self.ls._get_lock().is_owned(shared=0))
1513 1556
    self.assertTrue(compat.all(i.is_owned(shared=0)
1514 1557
                               for i in self.ls._get_lockdict().values()))
......
1520 1563
                               for name, lock in
1521 1564
                                 self.ls._get_lockdict().items()))
1522 1565

  
1566
    self.assertFalse(self.ls.check_owned("one", shared=0))
1567
    self.assertTrue(self.ls.check_owned("one", shared=1))
1568
    self.assertTrue(self.ls.check_owned("two", shared=0))
1569
    self.assertTrue(self.ls.check_owned("three", shared=0))
1570

  
1571
    # Downgrade second lock
1523 1572
    self.assertTrue(self.ls.downgrade(names="two"))
1524 1573
    self.assertTrue(self.ls._get_lock().is_owned(shared=0))
1525 1574
    should_share = lambda name: [0, 1][int(name in ("one", "two"))]
......
1527 1576
                               for name, lock in
1528 1577
                                 self.ls._get_lockdict().items()))
1529 1578

  
1579
    self.assertFalse(self.ls.check_owned("one", shared=0))
1580
    self.assertTrue(self.ls.check_owned("one", shared=1))
1581
    self.assertFalse(self.ls.check_owned("two", shared=0))
1582
    self.assertTrue(self.ls.check_owned("two", shared=1))
1583
    self.assertTrue(self.ls.check_owned("three", shared=0))
1584

  
1530 1585
    # Downgrading the last exclusive lock to shared must downgrade the
1531 1586
    # lockset-internal lock too
1532 1587
    self.assertTrue(self.ls.downgrade(names="three"))
......
1534 1589
    self.assertTrue(compat.all(i.is_owned(shared=1)
1535 1590
                               for i in self.ls._get_lockdict().values()))
1536 1591

  
1592
    # Verify owned locks
1593
    for name in self.ls._names():
1594
      self.assertTrue(self.ls.check_owned(name, shared=1))
1595

  
1537 1596
    # Downgrading a shared lock must be a no-op
1538 1597
    self.assertTrue(self.ls.downgrade(names=["one", "three"]))
1539 1598
    self.assertTrue(self.ls._get_lock().is_owned(shared=1))
......
1657 1716
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
1658 1717
    self.GL.acquire(locking.LEVEL_NODEGROUP, ['g2'])
1659 1718
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
1719
    self.assertTrue(self.GL.check_owned(locking.LEVEL_NODE, ["n1", "n2"],
1720
                                        shared=1))
1721
    self.assertFalse(self.GL.check_owned(locking.LEVEL_INSTANCE, ["i1", "i3"]))
1660 1722
    self.GL.release(locking.LEVEL_NODE, ['n2'])
1661 1723
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODE), set(['n1']))
1662 1724
    self.assertEquals(self.GL.list_owned(locking.LEVEL_NODEGROUP), set(['g2']))

Also available in: Unified diff