Revision 24d16f76
b/lib/client/gnt_debug.py | ||
---|---|---|
479 | 479 |
""" |
480 | 480 |
selected_fields = ParseFields(opts.output, _LIST_LOCKS_DEF_FIELDS) |
481 | 481 |
|
482 |
if not opts.no_headers: |
|
483 |
headers = { |
|
484 |
"name": "Name", |
|
485 |
"mode": "Mode", |
|
486 |
"owner": "Owner", |
|
487 |
"pending": "Pending", |
|
488 |
} |
|
489 |
else: |
|
490 |
headers = None |
|
482 |
def _DashIfNone(fn): |
|
483 |
def wrapper(value): |
|
484 |
if not value: |
|
485 |
return "-" |
|
486 |
return fn(value) |
|
487 |
return wrapper |
|
488 |
|
|
489 |
def _FormatPending(value): |
|
490 |
"""Format pending acquires. |
|
491 |
|
|
492 |
""" |
|
493 |
return utils.CommaJoin("%s:%s" % (mode, ",".join(threads)) |
|
494 |
for mode, threads in value) |
|
495 |
|
|
496 |
# Format raw values |
|
497 |
fmtoverride = { |
|
498 |
"mode": (_DashIfNone(str), False), |
|
499 |
"owner": (_DashIfNone(",".join), False), |
|
500 |
"pending": (_DashIfNone(_FormatPending), False), |
|
501 |
} |
|
491 | 502 |
|
492 | 503 |
while True: |
493 |
# Not reusing client as interval might be too long |
|
494 |
output = GetClient().QueryLocks(selected_fields, False) |
|
495 |
|
|
496 |
# change raw values to nicer strings |
|
497 |
for row in output: |
|
498 |
for idx, field in enumerate(selected_fields): |
|
499 |
val = row[idx] |
|
500 |
|
|
501 |
if field in ("mode", "owner", "pending") and not val: |
|
502 |
val = "-" |
|
503 |
elif field == "owner": |
|
504 |
val = ",".join(val) |
|
505 |
elif field == "pending": |
|
506 |
val = utils.CommaJoin("%s:%s" % (mode, ",".join(threads)) |
|
507 |
for mode, threads in val) |
|
508 |
|
|
509 |
row[idx] = str(val) |
|
510 |
|
|
511 |
data = GenerateTable(separator=opts.separator, headers=headers, |
|
512 |
fields=selected_fields, data=output) |
|
513 |
for line in data: |
|
514 |
ToStdout(line) |
|
504 |
ret = GenericList(constants.QR_LOCK, selected_fields, None, None, |
|
505 |
opts.separator, not opts.no_headers, |
|
506 |
format_override=fmtoverride) |
|
507 |
|
|
508 |
if ret != constants.EXIT_SUCCESS: |
|
509 |
return ret |
|
515 | 510 |
|
516 | 511 |
if not opts.interval: |
517 | 512 |
break |
b/lib/constants.py | ||
---|---|---|
951 | 951 |
# Query resources |
952 | 952 |
QR_INSTANCE = "instance" |
953 | 953 |
QR_NODE = "node" |
954 |
QR_LOCK = "lock" |
|
954 | 955 |
|
955 | 956 |
#: List of resources which can be queried using L{opcodes.OpQuery} |
956 | 957 |
QR_OP_QUERY = frozenset([QR_INSTANCE, QR_NODE]) |
957 | 958 |
|
958 | 959 |
#: List of resources which can be queried using LUXI |
959 | 960 |
QR_OP_LUXI = QR_OP_QUERY.union([ |
961 |
QR_LOCK, |
|
960 | 962 |
]) |
961 | 963 |
|
962 | 964 |
# Query field types |
b/lib/locking.py | ||
---|---|---|
32 | 32 |
import weakref |
33 | 33 |
import logging |
34 | 34 |
import heapq |
35 |
import operator |
|
35 | 36 |
|
36 | 37 |
from ganeti import errors |
37 | 38 |
from ganeti import utils |
38 | 39 |
from ganeti import compat |
40 |
from ganeti import query |
|
39 | 41 |
|
40 | 42 |
|
41 | 43 |
_EXCLUSIVE_TEXT = "exclusive" |
42 | 44 |
_SHARED_TEXT = "shared" |
45 |
_DELETED_TEXT = "deleted" |
|
43 | 46 |
|
44 | 47 |
_DEFAULT_PRIORITY = 0 |
45 | 48 |
|
... | ... | |
432 | 435 |
if monitor: |
433 | 436 |
monitor.RegisterLock(self) |
434 | 437 |
|
435 |
def GetInfo(self, fields):
|
|
438 |
def GetInfo(self, requested):
|
|
436 | 439 |
"""Retrieves information for querying locks. |
437 | 440 |
|
438 |
@type fields: list of strings
|
|
439 |
@param fields: List of fields to return
|
|
441 |
@type requested: set
|
|
442 |
@param requested: Requested information, see C{query.LQ_*}
|
|
440 | 443 |
|
441 | 444 |
""" |
442 | 445 |
self.__lock.acquire() |
443 | 446 |
try: |
444 |
info = [] |
|
445 |
|
|
446 | 447 |
# Note: to avoid unintentional race conditions, no references to |
447 | 448 |
# modifiable objects should be returned unless they were created in this |
448 | 449 |
# function. |
449 |
for fname in fields: |
|
450 |
if fname == "name": |
|
451 |
info.append(self.name) |
|
452 |
elif fname == "mode": |
|
453 |
if self.__deleted: |
|
454 |
info.append("deleted") |
|
455 |
assert not (self.__exc or self.__shr) |
|
456 |
elif self.__exc: |
|
457 |
info.append(_EXCLUSIVE_TEXT) |
|
458 |
elif self.__shr: |
|
459 |
info.append(_SHARED_TEXT) |
|
460 |
else: |
|
461 |
info.append(None) |
|
462 |
elif fname == "owner": |
|
463 |
if self.__exc: |
|
464 |
owner = [self.__exc] |
|
465 |
else: |
|
466 |
owner = self.__shr |
|
467 |
|
|
468 |
if owner: |
|
469 |
assert not self.__deleted |
|
470 |
info.append([i.getName() for i in owner]) |
|
471 |
else: |
|
472 |
info.append(None) |
|
473 |
elif fname == "pending": |
|
474 |
data = [] |
|
475 |
|
|
476 |
# Sorting instead of copying and using heaq functions for simplicity |
|
477 |
for (_, prioqueue) in sorted(self.__pending): |
|
478 |
for cond in prioqueue: |
|
479 |
if cond.shared: |
|
480 |
mode = _SHARED_TEXT |
|
481 |
else: |
|
482 |
mode = _EXCLUSIVE_TEXT |
|
483 |
|
|
484 |
# This function should be fast as it runs with the lock held. |
|
485 |
# Hence not using utils.NiceSort. |
|
486 |
data.append((mode, sorted(i.getName() |
|
487 |
for i in cond.get_waiting()))) |
|
488 |
|
|
489 |
info.append(data) |
|
450 |
mode = None |
|
451 |
owner_names = None |
|
452 |
|
|
453 |
if query.LQ_MODE in requested: |
|
454 |
if self.__deleted: |
|
455 |
mode = _DELETED_TEXT |
|
456 |
assert not (self.__exc or self.__shr) |
|
457 |
elif self.__exc: |
|
458 |
mode = _EXCLUSIVE_TEXT |
|
459 |
elif self.__shr: |
|
460 |
mode = _SHARED_TEXT |
|
461 |
|
|
462 |
# Current owner(s) are wanted |
|
463 |
if query.LQ_OWNER in requested: |
|
464 |
if self.__exc: |
|
465 |
owner = [self.__exc] |
|
490 | 466 |
else: |
491 |
raise errors.OpExecError("Invalid query field '%s'" % fname) |
|
467 |
owner = self.__shr |
|
468 |
|
|
469 |
if owner: |
|
470 |
assert not self.__deleted |
|
471 |
owner_names = [i.getName() for i in owner] |
|
492 | 472 |
|
493 |
return info |
|
473 |
# Pending acquires are wanted |
|
474 |
if query.LQ_PENDING in requested: |
|
475 |
pending = [] |
|
476 |
|
|
477 |
# Sorting instead of copying and using heaq functions for simplicity |
|
478 |
for (_, prioqueue) in sorted(self.__pending): |
|
479 |
for cond in prioqueue: |
|
480 |
if cond.shared: |
|
481 |
pendmode = _SHARED_TEXT |
|
482 |
else: |
|
483 |
pendmode = _EXCLUSIVE_TEXT |
|
484 |
|
|
485 |
# List of names will be sorted in L{query._GetLockPending} |
|
486 |
pending.append((pendmode, [i.getName() |
|
487 |
for i in cond.get_waiting()])) |
|
488 |
else: |
|
489 |
pending = None |
|
490 |
|
|
491 |
return (self.name, mode, owner_names, pending) |
|
494 | 492 |
finally: |
495 | 493 |
self.__lock.release() |
496 | 494 |
|
... | ... | |
1344 | 1342 |
monitor=self._monitor), |
1345 | 1343 |
} |
1346 | 1344 |
|
1347 |
def QueryLocks(self, fields, sync):
|
|
1345 |
def QueryLocks(self, fields): |
|
1348 | 1346 |
"""Queries information from all locks. |
1349 | 1347 |
|
1350 | 1348 |
See L{LockMonitor.QueryLocks}. |
1351 | 1349 |
|
1352 | 1350 |
""" |
1353 |
return self._monitor.QueryLocks(fields, sync) |
|
1351 |
return self._monitor.QueryLocks(fields) |
|
1352 |
|
|
1353 |
def OldStyleQueryLocks(self, fields): |
|
1354 |
"""Queries information from all locks, returning old-style data. |
|
1355 |
|
|
1356 |
See L{LockMonitor.OldStyleQueryLocks}. |
|
1357 |
|
|
1358 |
""" |
|
1359 |
return self._monitor.OldStyleQueryLocks(fields) |
|
1354 | 1360 |
|
1355 | 1361 |
def _names(self, level): |
1356 | 1362 |
"""List the lock names at the given level. |
... | ... | |
1533 | 1539 |
self._locks[lock] = None |
1534 | 1540 |
|
1535 | 1541 |
@ssynchronized(_LOCK_ATTR) |
1536 |
def _GetLockInfo(self, fields):
|
|
1542 |
def _GetLockInfo(self, requested):
|
|
1537 | 1543 |
"""Get information from all locks while the monitor lock is held. |
1538 | 1544 |
|
1539 | 1545 |
""" |
1540 |
result = {}
|
|
1546 |
return [lock.GetInfo(requested) for lock in self._locks.keys()]
|
|
1541 | 1547 |
|
1542 |
for lock in self._locks.keys(): |
|
1543 |
assert lock.name not in result, "Found duplicate lock name" |
|
1544 |
result[lock.name] = lock.GetInfo(fields) |
|
1548 |
def _Query(self, fields): |
|
1549 |
"""Queries information from all locks. |
|
1545 | 1550 |
|
1546 |
return result |
|
1551 |
@type fields: list of strings |
|
1552 |
@param fields: List of fields to return |
|
1553 |
|
|
1554 |
""" |
|
1555 |
qobj = query.Query(query.LOCK_FIELDS, fields) |
|
1556 |
|
|
1557 |
# Get all data and sort by name |
|
1558 |
lockinfo = utils.NiceSort(self._GetLockInfo(qobj.RequestedData()), |
|
1559 |
key=operator.itemgetter(0)) |
|
1560 |
|
|
1561 |
return (qobj, query.LockQueryData(lockinfo)) |
|
1547 | 1562 |
|
1548 |
def QueryLocks(self, fields, sync):
|
|
1563 |
def QueryLocks(self, fields): |
|
1549 | 1564 |
"""Queries information from all locks. |
1550 | 1565 |
|
1551 | 1566 |
@type fields: list of strings |
1552 | 1567 |
@param fields: List of fields to return |
1553 |
@type sync: boolean |
|
1554 |
@param sync: Whether to operate in synchronous mode |
|
1555 | 1568 |
|
1556 | 1569 |
""" |
1557 |
if sync: |
|
1558 |
raise NotImplementedError("Synchronous queries are not implemented") |
|
1570 |
(qobj, ctx) = self._Query(fields) |
|
1559 | 1571 |
|
1560 |
# Get all data without sorting |
|
1561 |
result = self._GetLockInfo(fields) |
|
1572 |
# Prepare query response |
|
1573 |
return query.GetQueryResponse(qobj, ctx) |
|
1574 |
|
|
1575 |
def OldStyleQueryLocks(self, fields): |
|
1576 |
"""Queries information from all locks, returning old-style data. |
|
1577 |
|
|
1578 |
@type fields: list of strings |
|
1579 |
@param fields: List of fields to return |
|
1580 |
|
|
1581 |
""" |
|
1582 |
(qobj, ctx) = self._Query(fields) |
|
1562 | 1583 |
|
1563 |
# Sort by name |
|
1564 |
return [result[name] for name in utils.NiceSort(result.keys())] |
|
1584 |
return qobj.OldStyleQuery(ctx) |
b/lib/luxi.py | ||
---|---|---|
34 | 34 |
import time |
35 | 35 |
import errno |
36 | 36 |
import logging |
37 |
import warnings |
|
37 | 38 |
|
38 | 39 |
from ganeti import serializer |
39 | 40 |
from ganeti import constants |
... | ... | |
543 | 544 |
return self.CallMethod(REQ_QUERY_TAGS, (kind, name)) |
544 | 545 |
|
545 | 546 |
def QueryLocks(self, fields, sync): |
547 |
warnings.warn("This LUXI call is deprecated and will be removed, use" |
|
548 |
" Query(\"%s\", ...) instead" % constants.QR_LOCK) |
|
546 | 549 |
return self.CallMethod(REQ_QUERY_LOCKS, (fields, sync)) |
b/lib/query.py | ||
---|---|---|
42 | 42 |
IQ_LIVE, |
43 | 43 |
IQ_DISKUSAGE) = range(100, 103) |
44 | 44 |
|
45 |
(LQ_MODE, |
|
46 |
LQ_OWNER, |
|
47 |
LQ_PENDING) = range(10, 13) |
|
45 | 48 |
|
46 | 49 |
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$") |
47 | 50 |
TITLE_RE = re.compile(r"^[^\s]+$") |
... | ... | |
1003 | 1006 |
return _PrepareFieldList(fields) |
1004 | 1007 |
|
1005 | 1008 |
|
1009 |
class LockQueryData: |
|
1010 |
"""Data container for lock data queries. |
|
1011 |
|
|
1012 |
""" |
|
1013 |
def __init__(self, lockdata): |
|
1014 |
"""Initializes this class. |
|
1015 |
|
|
1016 |
""" |
|
1017 |
self.lockdata = lockdata |
|
1018 |
|
|
1019 |
def __iter__(self): |
|
1020 |
"""Iterate over all locks. |
|
1021 |
|
|
1022 |
""" |
|
1023 |
return iter(self.lockdata) |
|
1024 |
|
|
1025 |
|
|
1026 |
def _GetLockOwners(_, data): |
|
1027 |
"""Returns a sorted list of a lock's current owners. |
|
1028 |
|
|
1029 |
""" |
|
1030 |
(_, _, owners, _) = data |
|
1031 |
|
|
1032 |
if owners: |
|
1033 |
owners = utils.NiceSort(owners) |
|
1034 |
|
|
1035 |
return (constants.QRFS_NORMAL, owners) |
|
1036 |
|
|
1037 |
|
|
1038 |
def _GetLockPending(_, data): |
|
1039 |
"""Returns a sorted list of a lock's pending acquires. |
|
1040 |
|
|
1041 |
""" |
|
1042 |
(_, _, _, pending) = data |
|
1043 |
|
|
1044 |
if pending: |
|
1045 |
pending = [(mode, utils.NiceSort(names)) |
|
1046 |
for (mode, names) in pending] |
|
1047 |
|
|
1048 |
return (constants.QRFS_NORMAL, pending) |
|
1049 |
|
|
1050 |
|
|
1051 |
def _BuildLockFields(): |
|
1052 |
"""Builds list of fields for lock queries. |
|
1053 |
|
|
1054 |
""" |
|
1055 |
return _PrepareFieldList([ |
|
1056 |
(_MakeField("name", "Name", constants.QFT_TEXT), None, |
|
1057 |
lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, name)), |
|
1058 |
(_MakeField("mode", "Mode", constants.QFT_OTHER), LQ_MODE, |
|
1059 |
lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, mode)), |
|
1060 |
(_MakeField("owner", "Owner", constants.QFT_OTHER), LQ_OWNER, |
|
1061 |
_GetLockOwners), |
|
1062 |
(_MakeField("pending", "Pending", constants.QFT_OTHER), LQ_PENDING, |
|
1063 |
_GetLockPending), |
|
1064 |
]) |
|
1065 |
|
|
1066 |
|
|
1006 | 1067 |
#: Fields available for node queries |
1007 | 1068 |
NODE_FIELDS = _BuildNodeFields() |
1008 | 1069 |
|
1009 | 1070 |
#: Fields available for instance queries |
1010 | 1071 |
INSTANCE_FIELDS = _BuildInstanceFields() |
1072 |
|
|
1073 |
#: Fields available for lock queries |
|
1074 |
LOCK_FIELDS = _BuildLockFields() |
b/lib/server/masterd.py | ||
---|---|---|
56 | 56 |
from ganeti import bootstrap |
57 | 57 |
from ganeti import netutils |
58 | 58 |
from ganeti import objects |
59 |
from ganeti import query |
|
59 | 60 |
|
60 | 61 |
|
61 | 62 |
CLIENT_REQUEST_WORKERS = 16 |
... | ... | |
234 | 235 |
if req.what in constants.QR_OP_QUERY: |
235 | 236 |
result = self._Query(opcodes.OpQuery(what=req.what, fields=req.fields, |
236 | 237 |
filter=req.filter)) |
238 |
elif req.what == constants.QR_LOCK: |
|
239 |
if req.filter is not None: |
|
240 |
raise errors.OpPrereqError("Lock queries can't be filtered") |
|
241 |
return self.server.context.glm.QueryLocks(req.fields) |
|
237 | 242 |
elif req.what in constants.QR_OP_LUXI: |
238 | 243 |
raise NotImplementedError |
239 | 244 |
else: |
... | ... | |
248 | 253 |
if req.what in constants.QR_OP_QUERY: |
249 | 254 |
result = self._Query(opcodes.OpQueryFields(what=req.what, |
250 | 255 |
fields=req.fields)) |
256 |
elif req.what == constants.QR_LOCK: |
|
257 |
return query.QueryFields(query.LOCK_FIELDS, req.fields) |
|
251 | 258 |
elif req.what in constants.QR_OP_LUXI: |
252 | 259 |
raise NotImplementedError |
253 | 260 |
else: |
... | ... | |
323 | 330 |
elif method == luxi.REQ_QUERY_LOCKS: |
324 | 331 |
(fields, sync) = args |
325 | 332 |
logging.info("Received locks query request") |
326 |
return self.server.context.glm.QueryLocks(fields, sync) |
|
333 |
if sync: |
|
334 |
raise NotImplementedError("Synchronous queries are not implemented") |
|
335 |
return self.server.context.glm.OldStyleQueryLocks(fields) |
|
327 | 336 |
|
328 | 337 |
elif method == luxi.REQ_QUEUE_SET_DRAIN_FLAG: |
329 | 338 |
drain_flag = args |
b/test/ganeti.locking_unittest.py | ||
---|---|---|
30 | 30 |
import random |
31 | 31 |
import itertools |
32 | 32 |
|
33 |
from ganeti import constants |
|
33 | 34 |
from ganeti import locking |
34 | 35 |
from ganeti import errors |
35 | 36 |
from ganeti import utils |
36 | 37 |
from ganeti import compat |
38 |
from ganeti import objects |
|
39 |
from ganeti import query |
|
37 | 40 |
|
38 | 41 |
import testutils |
39 | 42 |
|
... | ... | |
773 | 776 |
prev.wait() |
774 | 777 |
|
775 | 778 |
# Check lock information |
776 |
self.assertEqual(self.sl.GetInfo(["name"]), [self.sl.name]) |
|
777 |
self.assertEqual(self.sl.GetInfo(["mode", "owner"]), |
|
778 |
["exclusive", [threading.currentThread().getName()]]) |
|
779 |
self.assertEqual(self.sl.GetInfo(["name", "pending"]), |
|
780 |
[self.sl.name, |
|
781 |
[(["exclusive", "shared"][int(bool(shared))], |
|
782 |
sorted([t.getName() for t in threads])) |
|
783 |
for acquires in [perprio[i] |
|
784 |
for i in sorted(perprio.keys())] |
|
785 |
for (shared, _, threads) in acquires]]) |
|
779 |
self.assertEqual(self.sl.GetInfo(set()), (self.sl.name, None, None, None)) |
|
780 |
self.assertEqual(self.sl.GetInfo(set([query.LQ_MODE, query.LQ_OWNER])), |
|
781 |
(self.sl.name, "exclusive", |
|
782 |
[threading.currentThread().getName()], None)) |
|
783 |
|
|
784 |
self._VerifyPrioPending(self.sl.GetInfo(set([query.LQ_PENDING])), perprio) |
|
786 | 785 |
|
787 | 786 |
# Let threads acquire the lock |
788 | 787 |
self.sl.release() |
... | ... | |
803 | 802 |
|
804 | 803 |
self.assertRaises(Queue.Empty, self.done.get_nowait) |
805 | 804 |
|
805 |
def _VerifyPrioPending(self, (name, mode, owner, pending), perprio): |
|
806 |
self.assertEqual(name, self.sl.name) |
|
807 |
self.assert_(mode is None) |
|
808 |
self.assert_(owner is None) |
|
809 |
|
|
810 |
self.assertEqual([(pendmode, sorted(waiting)) |
|
811 |
for (pendmode, waiting) in pending], |
|
812 |
[(["exclusive", "shared"][int(bool(shared))], |
|
813 |
sorted(t.getName() for t in threads)) |
|
814 |
for acquires in [perprio[i] |
|
815 |
for i in sorted(perprio.keys())] |
|
816 |
for (shared, _, threads) in acquires]) |
|
817 |
|
|
806 | 818 |
|
807 | 819 |
class TestSharedLockInCondition(_ThreadedTestCase): |
808 | 820 |
"""SharedLock as a condition lock tests""" |
... | ... | |
1638 | 1650 |
locks.append(locking.SharedLock(name, monitor=self.lm)) |
1639 | 1651 |
|
1640 | 1652 |
self.assertEqual(len(self.lm._locks), len(locks)) |
1641 |
|
|
1642 |
self.assertEqual(len(self.lm.QueryLocks(["name"], False)),
|
|
1643 |
100)
|
|
1653 |
result = objects.QueryResponse.FromDict(self.lm.QueryLocks(["name"])) |
|
1654 |
self.assertEqual(len(result.fields), 1)
|
|
1655 |
self.assertEqual(len(result.data), 100)
|
|
1644 | 1656 |
|
1645 | 1657 |
# Delete all locks |
1646 | 1658 |
del locks[:] |
... | ... | |
1684 | 1696 |
# Check order in which locks were added |
1685 | 1697 |
self.assertEqual([i.name for i in locks], expnames) |
1686 | 1698 |
|
1687 |
# Sync queries are not supported |
|
1688 |
self.assertRaises(NotImplementedError, self.lm.QueryLocks, ["name"], True) |
|
1689 |
|
|
1690 | 1699 |
# Check query result |
1691 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", "pending"], |
|
1692 |
False), |
|
1693 |
[[name, None, None, []] |
|
1700 |
result = self.lm.QueryLocks(["name", "mode", "owner", "pending"]) |
|
1701 |
self.assert_(isinstance(result, dict)) |
|
1702 |
response = objects.QueryResponse.FromDict(result) |
|
1703 |
self.assertEqual(response.data, |
|
1704 |
[[(constants.QRFS_NORMAL, name), |
|
1705 |
(constants.QRFS_NORMAL, None), |
|
1706 |
(constants.QRFS_NORMAL, None), |
|
1707 |
(constants.QRFS_NORMAL, [])] |
|
1694 | 1708 |
for name in utils.NiceSort(expnames)]) |
1709 |
self.assertEqual(len(response.fields), 4) |
|
1710 |
self.assertEqual(["name", "mode", "owner", "pending"], |
|
1711 |
[fdef.name for fdef in response.fields]) |
|
1695 | 1712 |
|
1696 | 1713 |
# Test exclusive acquire |
1697 | 1714 |
for tlock in locks[::4]: |
... | ... | |
1699 | 1716 |
try: |
1700 | 1717 |
def _GetExpResult(name): |
1701 | 1718 |
if tlock.name == name: |
1702 |
return [name, "exclusive", [threading.currentThread().getName()], |
|
1703 |
[]] |
|
1704 |
return [name, None, None, []] |
|
1705 |
|
|
1706 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", |
|
1707 |
"pending"], False), |
|
1719 |
return [(constants.QRFS_NORMAL, name), |
|
1720 |
(constants.QRFS_NORMAL, "exclusive"), |
|
1721 |
(constants.QRFS_NORMAL, |
|
1722 |
[threading.currentThread().getName()]), |
|
1723 |
(constants.QRFS_NORMAL, [])] |
|
1724 |
return [(constants.QRFS_NORMAL, name), |
|
1725 |
(constants.QRFS_NORMAL, None), |
|
1726 |
(constants.QRFS_NORMAL, None), |
|
1727 |
(constants.QRFS_NORMAL, [])] |
|
1728 |
|
|
1729 |
result = self.lm.QueryLocks(["name", "mode", "owner", "pending"]) |
|
1730 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1708 | 1731 |
[_GetExpResult(name) |
1709 | 1732 |
for name in utils.NiceSort(expnames)]) |
1710 | 1733 |
finally: |
... | ... | |
1756 | 1779 |
i.wait() |
1757 | 1780 |
|
1758 | 1781 |
# Check query result |
1759 |
for (name, mode, owner) in self.lm.QueryLocks(["name", "mode", |
|
1760 |
"owner"], False): |
|
1761 |
if name == tlock1.name: |
|
1762 |
self.assertEqual(mode, "shared") |
|
1763 |
self.assertEqual(set(owner), set(i.getName() for i in tthreads1)) |
|
1782 |
result = self.lm.QueryLocks(["name", "mode", "owner"]) |
|
1783 |
response = objects.QueryResponse.FromDict(result) |
|
1784 |
for (name, mode, owner) in response.data: |
|
1785 |
(name_status, name_value) = name |
|
1786 |
(owner_status, owner_value) = owner |
|
1787 |
|
|
1788 |
self.assertEqual(name_status, constants.QRFS_NORMAL) |
|
1789 |
self.assertEqual(owner_status, constants.QRFS_NORMAL) |
|
1790 |
|
|
1791 |
if name_value == tlock1.name: |
|
1792 |
self.assertEqual(mode, (constants.QRFS_NORMAL, "shared")) |
|
1793 |
self.assertEqual(set(owner_value), |
|
1794 |
set(i.getName() for i in tthreads1)) |
|
1764 | 1795 |
continue |
1765 | 1796 |
|
1766 |
if name == tlock2.name: |
|
1767 |
self.assertEqual(mode, "shared")
|
|
1768 |
self.assertEqual(owner, [tthread2.getName()]) |
|
1797 |
if name_value == tlock2.name:
|
|
1798 |
self.assertEqual(mode, (constants.QRFS_NORMAL, "shared"))
|
|
1799 |
self.assertEqual(owner_value, [tthread2.getName()])
|
|
1769 | 1800 |
continue |
1770 | 1801 |
|
1771 |
if name == tlock3.name: |
|
1772 |
self.assertEqual(mode, "exclusive")
|
|
1773 |
self.assertEqual(owner, [tthread3.getName()]) |
|
1802 |
if name_value == tlock3.name:
|
|
1803 |
self.assertEqual(mode, (constants.QRFS_NORMAL, "exclusive"))
|
|
1804 |
self.assertEqual(owner_value, [tthread3.getName()])
|
|
1774 | 1805 |
continue |
1775 | 1806 |
|
1776 |
self.assert_(name in expnames) |
|
1777 |
self.assert_(mode is None)
|
|
1778 |
self.assert_(owner is None) |
|
1807 |
self.assert_(name_value in expnames)
|
|
1808 |
self.assertEqual(mode, (constants.QRFS_NORMAL, None))
|
|
1809 |
self.assert_(owner_value is None)
|
|
1779 | 1810 |
|
1780 | 1811 |
# Release locks again |
1781 | 1812 |
releaseev.set() |
1782 | 1813 |
|
1783 | 1814 |
self._waitThreads() |
1784 | 1815 |
|
1785 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1786 |
[[name, None, None] |
|
1816 |
result = self.lm.QueryLocks(["name", "mode", "owner"]) |
|
1817 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1818 |
[[(constants.QRFS_NORMAL, name), |
|
1819 |
(constants.QRFS_NORMAL, None), |
|
1820 |
(constants.QRFS_NORMAL, None)] |
|
1787 | 1821 |
for name in utils.NiceSort(expnames)]) |
1788 | 1822 |
|
1789 | 1823 |
def testDelete(self): |
1790 | 1824 |
lock = locking.SharedLock("TestLock", monitor=self.lm) |
1791 | 1825 |
|
1792 | 1826 |
self.assertEqual(len(self.lm._locks), 1) |
1793 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1794 |
[[lock.name, None, None]]) |
|
1827 |
result = self.lm.QueryLocks(["name", "mode", "owner"]) |
|
1828 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1829 |
[[(constants.QRFS_NORMAL, lock.name), |
|
1830 |
(constants.QRFS_NORMAL, None), |
|
1831 |
(constants.QRFS_NORMAL, None)]]) |
|
1795 | 1832 |
|
1796 | 1833 |
lock.delete() |
1797 | 1834 |
|
1798 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1799 |
[[lock.name, "deleted", None]]) |
|
1835 |
result = self.lm.QueryLocks(["name", "mode", "owner"]) |
|
1836 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1837 |
[[(constants.QRFS_NORMAL, lock.name), |
|
1838 |
(constants.QRFS_NORMAL, "deleted"), |
|
1839 |
(constants.QRFS_NORMAL, None)]]) |
|
1800 | 1840 |
self.assertEqual(len(self.lm._locks), 1) |
1801 | 1841 |
|
1802 | 1842 |
def testPending(self): |
... | ... | |
1815 | 1855 |
lock.acquire() |
1816 | 1856 |
try: |
1817 | 1857 |
self.assertEqual(len(self.lm._locks), 1) |
1818 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1819 |
[[lock.name, "exclusive", |
|
1820 |
[threading.currentThread().getName()]]]) |
|
1858 |
result = self.lm.QueryLocks(["name", "mode", "owner"]) |
|
1859 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1860 |
[[(constants.QRFS_NORMAL, lock.name), |
|
1861 |
(constants.QRFS_NORMAL, "exclusive"), |
|
1862 |
(constants.QRFS_NORMAL, |
|
1863 |
[threading.currentThread().getName()])]]) |
|
1821 | 1864 |
|
1822 | 1865 |
threads = [] |
1823 | 1866 |
|
... | ... | |
1843 | 1886 |
|
1844 | 1887 |
# All acquires are waiting now |
1845 | 1888 |
if shared: |
1846 |
pending = [("shared", sorted([t.getName() for t in threads]))]
|
|
1889 |
pending = [("shared", utils.NiceSort(t.getName() for t in threads))]
|
|
1847 | 1890 |
else: |
1848 | 1891 |
pending = [("exclusive", [t.getName()]) for t in threads] |
1849 | 1892 |
|
1850 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", |
|
1851 |
"pending"], False), |
|
1852 |
[[lock.name, "exclusive", |
|
1853 |
[threading.currentThread().getName()], |
|
1854 |
pending]]) |
|
1893 |
result = self.lm.QueryLocks(["name", "mode", "owner", "pending"]) |
|
1894 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1895 |
[[(constants.QRFS_NORMAL, lock.name), |
|
1896 |
(constants.QRFS_NORMAL, "exclusive"), |
|
1897 |
(constants.QRFS_NORMAL, |
|
1898 |
[threading.currentThread().getName()]), |
|
1899 |
(constants.QRFS_NORMAL, pending)]]) |
|
1855 | 1900 |
|
1856 | 1901 |
self.assertEqual(len(self.lm._locks), 1) |
1857 | 1902 |
finally: |
... | ... | |
1860 | 1905 |
self._waitThreads() |
1861 | 1906 |
|
1862 | 1907 |
# No pending acquires |
1863 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner", "pending"], |
|
1864 |
False), |
|
1865 |
[[lock.name, None, None, []]]) |
|
1908 |
result = self.lm.QueryLocks(["name", "mode", "owner", "pending"]) |
|
1909 |
self.assertEqual(objects.QueryResponse.FromDict(result).data, |
|
1910 |
[[(constants.QRFS_NORMAL, lock.name), |
|
1911 |
(constants.QRFS_NORMAL, None), |
|
1912 |
(constants.QRFS_NORMAL, None), |
|
1913 |
(constants.QRFS_NORMAL, [])]]) |
|
1866 | 1914 |
|
1867 | 1915 |
self.assertEqual(len(self.lm._locks), 1) |
1868 | 1916 |
|
Also available in: Unified diff