From 966373fcfbdc5643d4e127fa0322a2e7fd47156e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20D=C3=A9nes?= Date: Mon, 11 Jul 2022 15:16:12 +0300 Subject: [PATCH] scylla-gdb.py: fix disagreement between std_deque len() and iter() std_deque implementation was broken, with __len__() and __iter__() disagreeing about the size of the container. Turns out both are wrong in certain situations. Fix the iteration logic and re-base both __len__() and __iter__() on the same node iteration code to prevent future disagreements. --- scylla-gdb.py | 70 +++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/scylla-gdb.py b/scylla-gdb.py index e1e444ae43..e4b1c1c403 100755 --- a/scylla-gdb.py +++ b/scylla-gdb.py @@ -562,39 +562,6 @@ class std_deque: # should reflect the value of _GLIBCXX_DEQUE_BUF_SIZE DEQUE_BUF_SIZE = 512 - class iterator: - def __init__(self, ref, buf_size): - self.cur = ref['_M_cur'] - self.first = ref['_M_first'] - self.last = ref['_M_last'] - self.node = ref['_M_node'] - self.buf_size = buf_size - - def _set_node(self, node): - self.first = node.dereference() - self.last = self.first + self.buf_size - self.node = node - - def __eq__(self, other): - return self.node == other.node and self.cur == other.cur - - def __str__(self): - return "{{node=0x{:x}, first=0x{:x}, last=0x{:x}, cur=0x{:x}}}".format( - int(self.node), - int(self.first), - int(self.last), - int(self.cur)) - - def next(self): - self.cur += 1 - if self.cur == self.last: - self._set_node(self.node + 1) - self.cur = self.first - - def get(self): - return self.cur.dereference() - - def __init__(self, ref): self.ref = ref self.value_type = self.ref.type.strip_typedefs().template_argument(0) @@ -603,12 +570,29 @@ class std_deque: else: self.buf_size = 1 + def _foreach_node(self): + node_it = self.ref['_M_impl']['_M_start'] + node_end = self.ref['_M_impl']['_M_finish'] + node = node_it['_M_node'] + it = node_it['_M_first'] + end = node_it['_M_last'] + + if not bool(node): + return + + while node != node_end['_M_node']: + yield it, end + node = node + 1 + it = node.dereference() + end = it + self.buf_size + + yield node_end['_M_first'], node_end['_M_cur'] + def __len__(self): - start = self.ref['_M_impl']['_M_start'] - finish = self.ref['_M_impl']['_M_finish'] - return (self.buf_size * (max(1, finish['_M_node'] - start['_M_node']) - 1) + - start['_M_last'] - start['_M_cur'] + - finish['_M_cur'] - finish['_M_first']) + l = 0 + for start, end in self._foreach_node(): + l += (end - start) + return l def __nonzero__(self): return self.__len__() > 0 @@ -617,12 +601,10 @@ class std_deque: return self.__len__() > 0 def __iter__(self): - it = std_deque.iterator(self.ref['_M_impl']['_M_start'], self.buf_size) - finish = std_deque.iterator(self.ref['_M_impl']['_M_finish'], self.buf_size) - - while it != finish: - yield it.get() - it.next() + for it, end in self._foreach_node(): + while it != end: + yield it.dereference() + it += 1 def __str__(self): items = [str(item) for item in self]