101
100
class CachingParentsProvider(object):
102
"""A parents provider which will cache the revision => parents in a dict.
104
This is useful for providers that have an expensive lookup.
101
"""A parents provider which will cache the revision => parents as a dict.
103
This is useful for providers which have an expensive look up.
105
Either a ParentsProvider or a get_parent_map-like callback may be
106
supplied. If it provides extra un-asked-for parents, they will be cached,
107
but filtered out of get_parent_map.
109
The cache is enabled by default, but may be disabled and re-enabled.
111
def __init__(self, parent_provider=None, get_parent_map=None):
107
def __init__(self, parent_provider):
114
:param parent_provider: The ParentProvider to use. It or
115
get_parent_map must be supplied.
116
:param get_parent_map: The get_parent_map callback to use. It or
117
parent_provider must be supplied.
108
119
self._real_provider = parent_provider
109
# Theoretically we could use an LRUCache here
120
if get_parent_map is None:
121
self._get_parent_map = self._real_provider.get_parent_map
123
self._get_parent_map = get_parent_map
125
self._cache_misses = True
112
127
def __repr__(self):
113
128
return "%s(%r)" % (self.__class__.__name__, self._real_provider)
130
def enable_cache(self, cache_misses=True):
132
if self._cache is not None:
133
raise AssertionError('Cache enabled when already enabled.')
135
self._cache_misses = cache_misses
137
def disable_cache(self):
138
"""Disable and clear the cache."""
141
def get_cached_map(self):
142
"""Return any cached get_parent_map values."""
143
if self._cache is None:
145
return dict((k, v) for k, v in self._cache.items()
115
148
def get_parent_map(self, keys):
116
"""See _StackedParentsProvider.get_parent_map"""
118
# If the _real_provider doesn't have a key, we cache a value of None,
119
# which we then later use to realize we cannot provide a value for that
126
if value is not None:
127
parent_map[key] = value
132
new_parents = self._real_provider.get_parent_map(needed)
133
cache.update(new_parents)
134
parent_map.update(new_parents)
135
needed.difference_update(new_parents)
136
cache.update(dict.fromkeys(needed, None))
149
"""See _StackedParentsProvider.get_parent_map."""
150
# Hack to build up the caching logic.
151
ancestry = self._cache
153
# Caching is disabled.
154
missing_revisions = set(keys)
157
missing_revisions = set(key for key in keys if key not in ancestry)
158
if missing_revisions:
159
parent_map = self._get_parent_map(missing_revisions)
160
ancestry.update(parent_map)
161
if self._cache_misses:
162
# None is never a valid parents list, so it can be used to
164
ancestry.update(dict((k, None) for k in missing_revisions
165
if k not in parent_map))
166
present_keys = [k for k in keys if ancestry.get(k) is not None]
167
return dict((k, ancestry[k]) for k in present_keys)
140
170
class Graph(object):