From 0fc9df23884c5cacb6be2f9866bd5c8a70f8f5e1 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Thu, 31 Oct 2013 20:03:39 +0000 Subject: 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. --- larch/refcountstore.py | 6 +----- 1 file changed, 1 insertion(+), 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): -- cgit v1.2.1