diff options
author | Lars Wirzenius <liw@liw.fi> | 2013-10-31 20:03:39 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2013-11-06 20:20:06 +0000 |
commit | 0fc9df23884c5cacb6be2f9866bd5c8a70f8f5e1 (patch) | |
tree | d9fdf1670d742423bfcd7eef5c4b4f9f28eddf26 | |
parent | 267b049865cc239e98847ea013dd9c88abe3f8e6 (diff) | |
download | larch-0fc9df23884c5cacb6be2f9866bd5c8a70f8f5e1.tar.gz |
Fix KeyError for missing refcount
We would sometimes, rarely, have a crash that looked like this:
File "..refcountstore.py", line 76, in get_refcount
return self.refcounts[node_id]
KeyError: 32970
In other words, the object keeping track of reference counts for
B-tree nodes would think it doesn't have the reference count for a
node, when it should have it.
After much debugging, by myself and Itamar Turner-Trauring, and
greatly helped by a repeatable test case provided by Rob Kendrick,
this was tracked to an optimisation in the set_refcount method, which
would remove (to save memory) the refcount for a node (remove the
entry for a node's id in the refcount dict), when the refcount was set
to zero. Unfortunately this conflicted with an assumption in
get_refcount that a refcount for a node that was in the dirty set was
actually present in the refcount dict.
The bug fix is easy: don't remove the node from the refcount dict, and
eat the (very minor) memory consumption hit, in the name of
correctness.
-rw-r--r-- | larch/refcountstore.py | 6 |
1 files changed, 1 insertions, 5 deletions
diff --git a/larch/refcountstore.py b/larch/refcountstore.py index 0aea53e..18fb9e7 100644 --- a/larch/refcountstore.py +++ b/larch/refcountstore.py @@ -78,11 +78,7 @@ class RefcountStore(object): def set_refcount(self, node_id, refcount): '''Set the reference count for a given node.''' tracing.trace('setting refcoutn for %s to %s' % (node_id, refcount)) - if refcount == 0: - if node_id in self.refcounts: - del self.refcounts[node_id] - else: - self.refcounts[node_id] = refcount + self.refcounts[node_id] = refcount self.dirty.add(node_id) def save_refcounts(self): |