27
27
from bisect import bisect_right
28
28
from cStringIO import StringIO
31
32
from bzrlib.lazy_import import lazy_import
32
33
lazy_import(globals(), """
1118
1119
in the index list.
1121
def __init__(self, indices):
1122
def __init__(self, indices, reload_func=None):
1122
1123
"""Create a CombinedGraphIndex backed by indices.
1124
1125
:param indices: An ordered list of indices to query for data.
1126
:param reload_func: A function to call if we find we are missing an
1127
index. Should have the form reload_func() => True/False to indicate
1128
if reloading actually changed anything.
1126
1130
self._indices = indices
1131
self._reload_func = reload_func
1128
1133
def __repr__(self):
1129
1134
return "%s(%s)" % (
1181
1186
the most efficient order for the index.
1183
1188
seen_keys = set()
1184
for index in self._indices:
1185
for node in index.iter_all_entries():
1186
if node[1] not in seen_keys:
1188
seen_keys.add(node[1])
1191
for index in self._indices:
1192
for node in index.iter_all_entries():
1193
if node[1] not in seen_keys:
1195
seen_keys.add(node[1])
1197
except errors.NoSuchFile:
1198
self._reload_or_raise()
1190
1200
def iter_entries(self, keys):
1191
1201
"""Iterate over keys within the index.
1199
1209
efficient order for the index.
1201
1211
keys = set(keys)
1202
for index in self._indices:
1214
for index in self._indices:
1217
for node in index.iter_entries(keys):
1218
keys.remove(node[1])
1205
for node in index.iter_entries(keys):
1206
keys.remove(node[1])
1221
except errors.NoSuchFile:
1222
self._reload_or_raise()
1209
1224
def iter_entries_prefix(self, keys):
1210
1225
"""Iterate over keys within the index using prefix matching.
1232
1247
seen_keys = set()
1233
for index in self._indices:
1234
for node in index.iter_entries_prefix(keys):
1235
if node[1] in seen_keys:
1237
seen_keys.add(node[1])
1250
for index in self._indices:
1251
for node in index.iter_entries_prefix(keys):
1252
if node[1] in seen_keys:
1254
seen_keys.add(node[1])
1257
except errors.NoSuchFile:
1258
self._reload_or_raise()
1240
1260
def key_count(self):
1241
1261
"""Return an estimate of the number of keys in this index.
1243
1263
For CombinedGraphIndex this is approximated by the sum of the keys of
1244
1264
the child indices. As child indices may have duplicate keys this can
1245
1265
have a maximum error of the number of child indices * largest number of
1246
1266
keys in any index.
1248
return sum((index.key_count() for index in self._indices), 0)
1270
return sum((index.key_count() for index in self._indices), 0)
1271
except errors.NoSuchFile:
1272
self._reload_or_raise()
1274
def _reload_or_raise(self):
1275
"""We just got a NoSuchFile exception.
1277
Try to reload the indices, if it fails, just raise the current
1280
if self._reload_func is None:
1282
exc_type, exc_value, exc_traceback = sys.exc_info()
1283
trace.mutter('Trying to reload after getting exception: %s',
1285
if not self._reload_func():
1286
# We tried to reload, but nothing changed, so we fail anyway
1287
trace.mutter('_reload_func indicated nothing has changed.'
1288
' Raising original exception.')
1289
raise exc_type, exc_value, exc_traceback
1250
1291
def validate(self):
1251
1292
"""Validate that everything in the index can be accessed."""
1252
for index in self._indices:
1295
for index in self._indices:
1298
except errors.NoSuchFile:
1299
self._reload_or_raise()
1256
1302
class InMemoryGraphIndex(GraphIndexBuilder):