~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lru_cache.py

  • Committer: Martin Pool
  • Date: 2009-07-24 03:15:56 UTC
  • mfrom: (4565 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4566.
  • Revision ID: mbp@sourcefrog.net-20090724031556-5zyef6f1ixtn6r3z
merge news

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008 Canonical Ltd
 
1
# Copyright (C) 2006, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
48
48
                                     self.next_key, prev_key)
49
49
 
50
50
    def run_cleanup(self):
51
 
        if self.cleanup is not None:
52
 
            self.cleanup(self.key, self.value)
53
 
        self.cleanup = None
54
 
        # Just make sure to break any refcycles, etc
55
 
        self.value = None
 
51
        try:
 
52
            if self.cleanup is not None:
 
53
                self.cleanup(self.key, self.value)
 
54
        finally:
 
55
            # cleanup might raise an exception, but we want to make sure
 
56
            # to break refcycles, etc
 
57
            self.cleanup = None
 
58
            self.value = None
56
59
 
57
60
 
58
61
class LRUCache(object):
156
159
            raise ValueError('cannot use _null_key as a key')
157
160
        if key in self._cache:
158
161
            node = self._cache[key]
159
 
            node.run_cleanup()
160
 
            node.value = value
161
 
            node.cleanup = cleanup
 
162
            try:
 
163
                node.run_cleanup()
 
164
            finally:
 
165
                # Maintain the LRU properties, even if cleanup raises an
 
166
                # exception
 
167
                node.value = value
 
168
                node.cleanup = cleanup
 
169
                self._record_access(node)
162
170
        else:
163
171
            node = _LRUNode(key, value, cleanup=cleanup)
164
172
            self._cache[key] = node
165
 
        self._record_access(node)
 
173
            self._record_access(node)
166
174
 
167
175
        if len(self._cache) > self._max_cache:
168
176
            # Trigger the cleanup
241
249
        # If we have removed all entries, remove the head pointer as well
242
250
        if self._least_recently_used is None:
243
251
            self._most_recently_used = None
244
 
        node.run_cleanup()
245
 
        # Now remove this node from the linked list
246
 
        if node.prev is not None:
247
 
            node.prev.next_key = node.next_key
248
 
        if node.next_key is not _null_key:
249
 
            node_next = self._cache[node.next_key]
250
 
            node_next.prev = node.prev
251
 
        # And remove this node's pointers
252
 
        node.prev = None
253
 
        node.next_key = _null_key
 
252
        try:
 
253
            node.run_cleanup()
 
254
        finally:
 
255
            # cleanup might raise an exception, but we want to make sure to
 
256
            # maintain the linked list
 
257
            if node.prev is not None:
 
258
                node.prev.next_key = node.next_key
 
259
            if node.next_key is not _null_key:
 
260
                node_next = self._cache[node.next_key]
 
261
                node_next.prev = node.prev
 
262
            # And remove this node's pointers
 
263
            node.prev = None
 
264
            node.next_key = _null_key
254
265
 
255
266
    def _remove_lru(self):
256
267
        """Remove one entry from the lru, and handle consequences.