~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/index.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-10-28 18:16:14 UTC
  • mfrom: (3789.1.11 pack_retry_153786-1)
  • Revision ID: pqm@pqm.ubuntu.com-20081028181614-p3qlghekhffb6cbu
(jam) First part of fixing #153786,
        CombinedGraphIndex reloads index list and retries operation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
from bisect import bisect_right
28
28
from cStringIO import StringIO
29
29
import re
 
30
import sys
30
31
 
31
32
from bzrlib.lazy_import import lazy_import
32
33
lazy_import(globals(), """
1118
1119
    in the index list.
1119
1120
    """
1120
1121
 
1121
 
    def __init__(self, indices):
 
1122
    def __init__(self, indices, reload_func=None):
1122
1123
        """Create a CombinedGraphIndex backed by indices.
1123
1124
 
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.
1125
1129
        """
1126
1130
        self._indices = indices
 
1131
        self._reload_func = reload_func
1127
1132
 
1128
1133
    def __repr__(self):
1129
1134
        return "%s(%s)" % (
1181
1186
            the most efficient order for the index.
1182
1187
        """
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:
1187
 
                    yield node
1188
 
                    seen_keys.add(node[1])
 
1189
        while True:
 
1190
            try:
 
1191
                for index in self._indices:
 
1192
                    for node in index.iter_all_entries():
 
1193
                        if node[1] not in seen_keys:
 
1194
                            yield node
 
1195
                            seen_keys.add(node[1])
 
1196
                return
 
1197
            except errors.NoSuchFile:
 
1198
                self._reload_or_raise()
1189
1199
 
1190
1200
    def iter_entries(self, keys):
1191
1201
        """Iterate over keys within the index.
1199
1209
            efficient order for the index.
1200
1210
        """
1201
1211
        keys = set(keys)
1202
 
        for index in self._indices:
1203
 
            if not keys:
 
1212
        while True:
 
1213
            try:
 
1214
                for index in self._indices:
 
1215
                    if not keys:
 
1216
                        return
 
1217
                    for node in index.iter_entries(keys):
 
1218
                        keys.remove(node[1])
 
1219
                        yield node
1204
1220
                return
1205
 
            for node in index.iter_entries(keys):
1206
 
                keys.remove(node[1])
1207
 
                yield node
 
1221
            except errors.NoSuchFile:
 
1222
                self._reload_or_raise()
1208
1223
 
1209
1224
    def iter_entries_prefix(self, keys):
1210
1225
        """Iterate over keys within the index using prefix matching.
1230
1245
        if not keys:
1231
1246
            return
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:
1236
 
                    continue
1237
 
                seen_keys.add(node[1])
1238
 
                yield node
 
1248
        while True:
 
1249
            try:
 
1250
                for index in self._indices:
 
1251
                    for node in index.iter_entries_prefix(keys):
 
1252
                        if node[1] in seen_keys:
 
1253
                            continue
 
1254
                        seen_keys.add(node[1])
 
1255
                        yield node
 
1256
                return
 
1257
            except errors.NoSuchFile:
 
1258
                self._reload_or_raise()
1239
1259
 
1240
1260
    def key_count(self):
1241
1261
        """Return an estimate of the number of keys in this index.
1242
 
        
 
1262
 
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.
1247
1267
        """
1248
 
        return sum((index.key_count() for index in self._indices), 0)
 
1268
        while True:
 
1269
            try:
 
1270
                return sum((index.key_count() for index in self._indices), 0)
 
1271
            except errors.NoSuchFile:
 
1272
                self._reload_or_raise()
 
1273
 
 
1274
    def _reload_or_raise(self):
 
1275
        """We just got a NoSuchFile exception.
 
1276
 
 
1277
        Try to reload the indices, if it fails, just raise the current
 
1278
        exception.
 
1279
        """
 
1280
        if self._reload_func is None:
 
1281
            raise
 
1282
        exc_type, exc_value, exc_traceback = sys.exc_info()
 
1283
        trace.mutter('Trying to reload after getting exception: %s',
 
1284
                     exc_value)
 
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
1249
1290
 
1250
1291
    def validate(self):
1251
1292
        """Validate that everything in the index can be accessed."""
1252
 
        for index in self._indices:
1253
 
            index.validate()
 
1293
        while True:
 
1294
            try:
 
1295
                for index in self._indices:
 
1296
                    index.validate()
 
1297
                return
 
1298
            except errors.NoSuchFile:
 
1299
                self._reload_or_raise()
1254
1300
 
1255
1301
 
1256
1302
class InMemoryGraphIndex(GraphIndexBuilder):