~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/btree_index.py

  • Committer: Robert Collins
  • Date: 2010-04-08 04:34:03 UTC
  • mfrom: (5138 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5139.
  • Revision ID: robertc@robertcollins.net-20100408043403-56z0d07vdqrx7f3t
Update bugfix for 528114 to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
567
567
                    else:
568
568
                        # yield keys
569
569
                        for value in key_dict.itervalues():
570
 
                            yield (self, ) + value
 
570
                            yield (self, ) + tuple(value)
571
571
            else:
572
572
                yield (self, ) + key_dict
573
573
 
647
647
    memory except when very large walks are done.
648
648
    """
649
649
 
650
 
    def __init__(self, transport, name, size, unlimited_cache=False):
 
650
    def __init__(self, transport, name, size, unlimited_cache=False,
 
651
                 offset=0):
651
652
        """Create a B+Tree index object on the index name.
652
653
 
653
654
        :param transport: The transport to read data for the index from.
660
661
        :param unlimited_cache: If set to True, then instead of using an
661
662
            LRUCache with size _NODE_CACHE_SIZE, we will use a dict and always
662
663
            cache all leaf nodes.
 
664
        :param offset: The start of the btree index data isn't byte 0 of the
 
665
            file. Instead it starts at some point later.
663
666
        """
664
667
        self._transport = transport
665
668
        self._name = name
667
670
        self._file = None
668
671
        self._recommended_pages = self._compute_recommended_pages()
669
672
        self._root_node = None
 
673
        self._base_offset = offset
670
674
        # Default max size is 100,000 leave values
671
675
        self._leaf_value_cache = None # lru_cache.LRUCache(100*1000)
672
676
        if unlimited_cache:
1494
1498
        # list of (offset, length) regions of the file that should, evenually
1495
1499
        # be read in to data_ranges, either from 'bytes' or from the transport
1496
1500
        ranges = []
 
1501
        base_offset = self._base_offset
1497
1502
        for index in nodes:
1498
 
            offset = index * _PAGE_SIZE
 
1503
            offset = (index * _PAGE_SIZE)
1499
1504
            size = _PAGE_SIZE
1500
1505
            if index == 0:
1501
1506
                # Root node - special case
1505
1510
                    # The only case where we don't know the size, is for very
1506
1511
                    # small indexes. So we read the whole thing
1507
1512
                    bytes = self._transport.get_bytes(self._name)
1508
 
                    self._size = len(bytes)
 
1513
                    num_bytes = len(bytes)
 
1514
                    self._size = num_bytes - base_offset
1509
1515
                    # the whole thing should be parsed out of 'bytes'
1510
 
                    ranges.append((0, len(bytes)))
 
1516
                    ranges = [(start, min(_PAGE_SIZE, num_bytes - start))
 
1517
                        for start in xrange(base_offset, num_bytes, _PAGE_SIZE)]
1511
1518
                    break
1512
1519
            else:
1513
1520
                if offset > self._size:
1515
1522
                                         ' of the file %s > %s'
1516
1523
                                         % (offset, self._size))
1517
1524
                size = min(size, self._size - offset)
1518
 
            ranges.append((offset, size))
 
1525
            ranges.append((base_offset + offset, size))
1519
1526
        if not ranges:
1520
1527
            return
1521
1528
        elif bytes is not None:
1522
1529
            # already have the whole file
1523
 
            data_ranges = [(start, bytes[start:start+_PAGE_SIZE])
1524
 
                           for start in xrange(0, len(bytes), _PAGE_SIZE)]
 
1530
            data_ranges = [(start, bytes[start:start+size])
 
1531
                           for start, size in ranges]
1525
1532
        elif self._file is None:
1526
1533
            data_ranges = self._transport.readv(self._name, ranges)
1527
1534
        else:
1530
1537
                self._file.seek(offset)
1531
1538
                data_ranges.append((offset, self._file.read(size)))
1532
1539
        for offset, data in data_ranges:
 
1540
            offset -= base_offset
1533
1541
            if offset == 0:
1534
1542
                # extract the header
1535
1543
                offset, data = self._parse_header_from_bytes(data)