~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lru_cache.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-06-20 02:58:19 UTC
  • mfrom: (4464.1.2 fix-shelf)
  • Revision ID: pqm@pqm.ubuntu.com-20090620025819-9fkf33yr3dvtwh2o
(abentley) Fix #363444 by fixing pack parsing with 0-length records.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2006, 2008 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
17
17
"""A simple least-recently-used (LRU) cache."""
18
18
 
19
19
from bzrlib import (
 
20
    symbol_versioning,
20
21
    trace,
21
22
    )
22
23
 
47
48
                                     self.next_key, prev_key)
48
49
 
49
50
    def run_cleanup(self):
50
 
        try:
51
 
            if self.cleanup is not None:
52
 
                self.cleanup(self.key, self.value)
53
 
        finally:
54
 
            # cleanup might raise an exception, but we want to make sure
55
 
            # to break refcycles, etc
56
 
            self.cleanup = None
57
 
            self.value = None
 
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
58
56
 
59
57
 
60
58
class LRUCache(object):
61
59
    """A class which manages a cache of entries, removing unused ones."""
62
60
 
63
 
    def __init__(self, max_cache=100, after_cleanup_count=None):
 
61
    def __init__(self, max_cache=100, after_cleanup_count=None,
 
62
                 after_cleanup_size=symbol_versioning.DEPRECATED_PARAMETER):
 
63
        if symbol_versioning.deprecated_passed(after_cleanup_size):
 
64
            symbol_versioning.warn('LRUCache.__init__(after_cleanup_size) was'
 
65
                                   ' deprecated in 1.11. Use'
 
66
                                   ' after_cleanup_count instead.',
 
67
                                   DeprecationWarning)
 
68
            after_cleanup_count = after_cleanup_size
64
69
        self._cache = {}
65
70
        # The "HEAD" of the lru linked list
66
71
        self._most_recently_used = None
151
156
            raise ValueError('cannot use _null_key as a key')
152
157
        if key in self._cache:
153
158
            node = self._cache[key]
154
 
            try:
155
 
                node.run_cleanup()
156
 
            finally:
157
 
                # Maintain the LRU properties, even if cleanup raises an
158
 
                # exception
159
 
                node.value = value
160
 
                node.cleanup = cleanup
161
 
                self._record_access(node)
 
159
            node.run_cleanup()
 
160
            node.value = value
 
161
            node.cleanup = cleanup
162
162
        else:
163
163
            node = _LRUNode(key, value, cleanup=cleanup)
164
164
            self._cache[key] = node
165
 
            self._record_access(node)
 
165
        self._record_access(node)
166
166
 
167
167
        if len(self._cache) > self._max_cache:
168
168
            # Trigger the cleanup
241
241
        # If we have removed all entries, remove the head pointer as well
242
242
        if self._least_recently_used is None:
243
243
            self._most_recently_used = None
244
 
        try:
245
 
            node.run_cleanup()
246
 
        finally:
247
 
            # cleanup might raise an exception, but we want to make sure to
248
 
            # maintain the linked list
249
 
            if node.prev is not None:
250
 
                node.prev.next_key = node.next_key
251
 
            if node.next_key is not _null_key:
252
 
                node_next = self._cache[node.next_key]
253
 
                node_next.prev = node.prev
254
 
            # And remove this node's pointers
255
 
            node.prev = None
256
 
            node.next_key = _null_key
 
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
257
254
 
258
255
    def _remove_lru(self):
259
256
        """Remove one entry from the lru, and handle consequences.