Revision 44b4eddc lib/locking.py
b/lib/locking.py | ||
---|---|---|
434 | 434 |
|
435 | 435 |
# Register with lock monitor |
436 | 436 |
if monitor: |
437 |
logging.debug("Adding lock %s to monitor", name) |
|
437 | 438 |
monitor.RegisterLock(self) |
438 | 439 |
|
439 |
def GetInfo(self, requested): |
|
440 |
def GetLockInfo(self, requested):
|
|
440 | 441 |
"""Retrieves information for querying locks. |
441 | 442 |
|
442 | 443 |
@type requested: set |
... | ... | |
489 | 490 |
else: |
490 | 491 |
pending = None |
491 | 492 |
|
492 |
return (self.name, mode, owner_names, pending)
|
|
493 |
return [(self.name, mode, owner_names, pending)]
|
|
493 | 494 |
finally: |
494 | 495 |
self.__lock.release() |
495 | 496 |
|
... | ... | |
1638 | 1639 |
return self.__keyring[level].remove(names) |
1639 | 1640 |
|
1640 | 1641 |
|
1641 |
def _MonitorSortKey((num, item)):
|
|
1642 |
def _MonitorSortKey((item, idx, num)):
|
|
1642 | 1643 |
"""Sorting key function. |
1643 | 1644 |
|
1644 |
Sort by name, then by incoming order. |
|
1645 |
Sort by name, registration order and then order of information. This provides |
|
1646 |
a stable sort order over different providers, even if they return the same |
|
1647 |
name. |
|
1645 | 1648 |
|
1646 | 1649 |
""" |
1647 | 1650 |
(name, _, _, _) = item |
1648 | 1651 |
|
1649 |
return (utils.NiceSortKey(name), num) |
|
1652 |
return (utils.NiceSortKey(name), num, idx)
|
|
1650 | 1653 |
|
1651 | 1654 |
|
1652 | 1655 |
class LockMonitor(object): |
... | ... | |
1666 | 1669 |
self._locks = weakref.WeakKeyDictionary() |
1667 | 1670 |
|
1668 | 1671 |
@ssynchronized(_LOCK_ATTR) |
1669 |
def RegisterLock(self, lock):
|
|
1672 |
def RegisterLock(self, provider):
|
|
1670 | 1673 |
"""Registers a new lock. |
1671 | 1674 |
|
1675 |
@param provider: Object with a callable method named C{GetLockInfo}, taking |
|
1676 |
a single C{set} containing the requested information items |
|
1677 |
@note: It would be nicer to only receive the function generating the |
|
1678 |
requested information but, as it turns out, weak references to bound |
|
1679 |
methods (e.g. C{self.GetLockInfo}) are tricky; there are several |
|
1680 |
workarounds, but none of the ones I found works properly in combination |
|
1681 |
with a standard C{WeakKeyDictionary} |
|
1682 |
|
|
1672 | 1683 |
""" |
1673 |
logging.debug("Registering lock %s", lock.name) |
|
1674 |
assert lock not in self._locks, "Duplicate lock registration" |
|
1684 |
assert provider not in self._locks, "Duplicate registration" |
|
1675 | 1685 |
|
1676 | 1686 |
# There used to be a check for duplicate names here. As it turned out, when |
1677 | 1687 |
# a lock is re-created with the same name in a very short timeframe, the |
... | ... | |
1679 | 1689 |
# By keeping track of the order of incoming registrations, a stable sort |
1680 | 1690 |
# ordering can still be guaranteed. |
1681 | 1691 |
|
1682 |
self._locks[lock] = self._counter.next()
|
|
1692 |
self._locks[provider] = self._counter.next()
|
|
1683 | 1693 |
|
1684 |
@ssynchronized(_LOCK_ATTR) |
|
1685 | 1694 |
def _GetLockInfo(self, requested): |
1686 |
"""Get information from all locks while the monitor lock is held.
|
|
1695 |
"""Get information from all locks. |
|
1687 | 1696 |
|
1688 | 1697 |
""" |
1689 |
return [(num, lock.GetInfo(requested)) for lock, num in self._locks.items()] |
|
1698 |
# Must hold lock while getting consistent list of tracked items |
|
1699 |
self._lock.acquire(shared=1) |
|
1700 |
try: |
|
1701 |
items = self._locks.items() |
|
1702 |
finally: |
|
1703 |
self._lock.release() |
|
1704 |
|
|
1705 |
return [(info, idx, num) |
|
1706 |
for (provider, num) in items |
|
1707 |
for (idx, info) in enumerate(provider.GetLockInfo(requested))] |
|
1690 | 1708 |
|
1691 | 1709 |
def _Query(self, fields): |
1692 | 1710 |
"""Queries information from all locks. |
... | ... | |
1703 | 1721 |
key=_MonitorSortKey) |
1704 | 1722 |
|
1705 | 1723 |
# Extract lock information and build query data |
1706 |
return (qobj, query.LockQueryData(map(operator.itemgetter(1), lockinfo)))
|
|
1724 |
return (qobj, query.LockQueryData(map(operator.itemgetter(0), lockinfo)))
|
|
1707 | 1725 |
|
1708 | 1726 |
def QueryLocks(self, fields): |
1709 | 1727 |
"""Queries information from all locks. |
Also available in: Unified diff