/breezy/unstable

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/unstable

« back to all changes in this revision

Viewing changes to breezy/index.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-24 01:39:33 UTC
  • mfrom: (3815.3776.6)
  • Revision ID: jelmer@jelmer.uk-20170524013933-ir4y4tqtrsiz2ka2
New upstream snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
    ]
28
28
 
29
29
from bisect import bisect_right
30
 
from cStringIO import StringIO
31
30
import re
32
31
import sys
33
32
 
34
 
from bzrlib.lazy_import import lazy_import
 
33
from .lazy_import import lazy_import
35
34
lazy_import(globals(), """
36
 
from bzrlib import (
 
35
from breezy import (
37
36
    bisect_multi,
38
37
    revision as _mod_revision,
39
38
    trace,
40
39
    )
41
40
""")
42
 
from bzrlib import (
 
41
from . import (
43
42
    debug,
44
43
    errors,
45
44
    )
46
 
from bzrlib.static_tuple import StaticTuple
 
45
from .sixish import (
 
46
    BytesIO,
 
47
    )
 
48
from .static_tuple import StaticTuple
47
49
 
48
50
_HEADER_READV = (0, 200)
49
51
_OPTION_KEY_ELEMENTS = "key_elements="
249
251
    def finish(self):
250
252
        """Finish the index.
251
253
 
252
 
        :returns: cStringIO holding the full context of the index as it 
 
254
        :returns: cBytesIO holding the full context of the index as it 
253
255
        should be written to disk.
254
256
        """
255
257
        lines = [_SIGNATURE]
331
333
            lines.append("%s\x00%s\x00%s\x00%s\n" % (string_key, absent,
332
334
                '\t'.join(flattened_references), value))
333
335
        lines.append('\n')
334
 
        result = StringIO(''.join(lines))
 
336
        result = BytesIO(''.join(lines))
335
337
        if expected_bytes and len(result.getvalue()) != expected_bytes:
336
338
            raise errors.BzrError('Failed index creation. Internal error:'
337
339
                ' mismatched output length and expected length: %d %d' %
394
396
    def __init__(self, transport, name, size, unlimited_cache=False, offset=0):
395
397
        """Open an index called name on transport.
396
398
 
397
 
        :param transport: A bzrlib.transport.Transport.
 
399
        :param transport: A breezy.transport.Transport.
398
400
        :param name: A path to provide to transport API calls.
399
401
        :param size: The size of the index in bytes. This is used for bisection
400
402
            logic to perform partial index reads. While the size could be
432
434
    def __eq__(self, other):
433
435
        """Equal when self and other were created with the same parameters."""
434
436
        return (
435
 
            type(self) == type(other) and
 
437
            isinstance(self, type(other)) and
436
438
            self._transport == other._transport and
437
439
            self._name == other._name and
438
440
            self._size == other._size)
460
462
            if self._base_offset != 0:
461
463
                # This is wasteful, but it is better than dealing with
462
464
                # adjusting all the offsets, etc.
463
 
                stream = StringIO(stream.read()[self._base_offset:])
 
465
                stream = BytesIO(stream.read()[self._base_offset:])
464
466
        self._read_prefix(stream)
465
467
        self._expected_elements = 3 + self._key_length
466
468
        line_count = 0
749
751
                    key_dict = dicts.pop(-1)
750
752
                    # can't be empty or would not exist
751
753
                    item, value = key_dict.iteritems().next()
752
 
                    if type(value) == dict:
 
754
                    if isinstance(value, dict):
753
755
                        # push keys
754
756
                        dicts.extend(key_dict.itervalues())
755
757
                    else:
798
800
 
799
801
        :param location_keys: A list of location(byte offset), key tuples.
800
802
        :return: A list of (location_key, result) tuples as expected by
801
 
            bzrlib.bisect_multi.bisect_multi_bytes.
 
803
            breezy.bisect_multi.bisect_multi_bytes.
802
804
        """
803
805
        # Possible improvements:
804
806
        #  - only bisect lookup each key once
1228
1230
                # We read the whole range, most likely because the
1229
1231
                # Transport upcast our readv ranges into one long request
1230
1232
                # for enough total data to grab the whole index.
1231
 
                self._buffer_all(StringIO(data))
 
1233
                self._buffer_all(BytesIO(data))
1232
1234
                return
1233
1235
            if self._bisect_nodes is None:
1234
1236
                # this must be the start
1310
1312
            found_parents[key] = parents
1311
1313
        return found_parents
1312
1314
 
1313
 
    has_key = _has_key_from_parent_map
 
1315
    __contains__ = _has_key_from_parent_map
1314
1316
 
1315
1317
    def insert_index(self, pos, index, name=None):
1316
1318
        """Insert a new index in the list of indices to query.
1343
1345
                            yield node
1344
1346
                            seen_keys.add(node[1])
1345
1347
                return
1346
 
            except errors.NoSuchFile:
1347
 
                self._reload_or_raise()
 
1348
            except errors.NoSuchFile as e:
 
1349
                if not self._try_reload(e):
 
1350
                    raise
1348
1351
 
1349
1352
    def iter_entries(self, keys):
1350
1353
        """Iterate over keys within the index.
1372
1375
                    if index_hit:
1373
1376
                        hit_indices.append(index)
1374
1377
                break
1375
 
            except errors.NoSuchFile:
1376
 
                self._reload_or_raise()
 
1378
            except errors.NoSuchFile as e:
 
1379
                if not self._try_reload(e):
 
1380
                    raise
1377
1381
        self._move_to_front(hit_indices)
1378
1382
 
1379
1383
    def iter_entries_prefix(self, keys):
1414
1418
                    if index_hit:
1415
1419
                        hit_indices.append(index)
1416
1420
                break
1417
 
            except errors.NoSuchFile:
1418
 
                self._reload_or_raise()
 
1421
            except errors.NoSuchFile as e:
 
1422
                if not self._try_reload(e):
 
1423
                    raise
1419
1424
        self._move_to_front(hit_indices)
1420
1425
 
1421
1426
    def _move_to_front(self, hit_indices):
1559
1564
        while True:
1560
1565
            try:
1561
1566
                return sum((index.key_count() for index in self._indices), 0)
1562
 
            except errors.NoSuchFile:
1563
 
                self._reload_or_raise()
 
1567
            except errors.NoSuchFile as e:
 
1568
                if not self._try_reload(e):
 
1569
                    raise
1564
1570
 
1565
1571
    missing_keys = _missing_keys_from_parent_map
1566
1572
 
1567
 
    def _reload_or_raise(self):
 
1573
    def _try_reload(self, error):
1568
1574
        """We just got a NoSuchFile exception.
1569
1575
 
1570
1576
        Try to reload the indices, if it fails, just raise the current
1571
1577
        exception.
1572
1578
        """
1573
1579
        if self._reload_func is None:
1574
 
            raise
1575
 
        exc_type, exc_value, exc_traceback = sys.exc_info()
1576
 
        trace.mutter('Trying to reload after getting exception: %s',
1577
 
                     exc_value)
 
1580
            return False
 
1581
        trace.mutter('Trying to reload after getting exception: %s', error)
1578
1582
        if not self._reload_func():
1579
1583
            # We tried to reload, but nothing changed, so we fail anyway
1580
1584
            trace.mutter('_reload_func indicated nothing has changed.'
1581
1585
                         ' Raising original exception.')
1582
 
            raise exc_type, exc_value, exc_traceback
 
1586
            return False
 
1587
        return True
1583
1588
 
1584
1589
    def set_sibling_indices(self, sibling_combined_graph_indices):
1585
1590
        """Set the CombinedGraphIndex objects to reorder after reordering self.
1593
1598
                for index in self._indices:
1594
1599
                    index.validate()
1595
1600
                return
1596
 
            except errors.NoSuchFile:
1597
 
                self._reload_or_raise()
 
1601
            except errors.NoSuchFile as e:
 
1602
                if not self._try_reload(e):
 
1603
                    raise
1598
1604
 
1599
1605
 
1600
1606
class InMemoryGraphIndex(GraphIndexBuilder):
1720
1726
                    key_dict = dicts.pop(-1)
1721
1727
                    # can't be empty or would not exist
1722
1728
                    item, value = key_dict.iteritems().next()
1723
 
                    if type(value) == dict:
 
1729
                    if isinstance(value, dict):
1724
1730
                        # push keys
1725
1731
                        dicts.extend(key_dict.itervalues())
1726
1732
                    else: