~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/btree_index.py

  • Committer: Martin Pool
  • Date: 2010-01-29 14:09:05 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129140905-2uiarb6p8di1ywsr
Correction to url

from review: https://code.edge.launchpad.net/~mbp/bzr/doc/+merge/18250

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2008, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2008 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
33
33
    osutils,
34
34
    static_tuple,
35
35
    trace,
36
 
    transport,
37
36
    )
38
37
from bzrlib.index import _OPTION_NODE_REFS, _OPTION_KEY_ELEMENTS, _OPTION_LEN
 
38
from bzrlib.transport import get_transport
39
39
 
40
40
 
41
41
_BTSIGNATURE = "B+Tree Graph Index 2\n"
193
193
            new_backing_file, size = self._spill_mem_keys_without_combining()
194
194
        # Note: The transport here isn't strictly needed, because we will use
195
195
        #       direct access to the new_backing._file object
196
 
        new_backing = BTreeGraphIndex(transport.get_transport('.'),
197
 
                                      '<temp>', size)
 
196
        new_backing = BTreeGraphIndex(get_transport('.'), '<temp>', size)
198
197
        # GC will clean up the file
199
198
        new_backing._file = new_backing_file
200
199
        if self._combine_backing_indices:
568
567
                    else:
569
568
                        # yield keys
570
569
                        for value in key_dict.itervalues():
571
 
                            yield (self, ) + tuple(value)
 
570
                            yield (self, ) + value
572
571
            else:
573
572
                yield (self, ) + key_dict
574
573
 
648
647
    memory except when very large walks are done.
649
648
    """
650
649
 
651
 
    def __init__(self, transport, name, size, unlimited_cache=False,
652
 
                 offset=0):
 
650
    def __init__(self, transport, name, size, unlimited_cache=False):
653
651
        """Create a B+Tree index object on the index name.
654
652
 
655
653
        :param transport: The transport to read data for the index from.
662
660
        :param unlimited_cache: If set to True, then instead of using an
663
661
            LRUCache with size _NODE_CACHE_SIZE, we will use a dict and always
664
662
            cache all leaf nodes.
665
 
        :param offset: The start of the btree index data isn't byte 0 of the
666
 
            file. Instead it starts at some point later.
667
663
        """
668
664
        self._transport = transport
669
665
        self._name = name
671
667
        self._file = None
672
668
        self._recommended_pages = self._compute_recommended_pages()
673
669
        self._root_node = None
674
 
        self._base_offset = offset
675
670
        # Default max size is 100,000 leave values
676
671
        self._leaf_value_cache = None # lru_cache.LRUCache(100*1000)
677
672
        if unlimited_cache:
1499
1494
        # list of (offset, length) regions of the file that should, evenually
1500
1495
        # be read in to data_ranges, either from 'bytes' or from the transport
1501
1496
        ranges = []
1502
 
        base_offset = self._base_offset
1503
1497
        for index in nodes:
1504
 
            offset = (index * _PAGE_SIZE)
 
1498
            offset = index * _PAGE_SIZE
1505
1499
            size = _PAGE_SIZE
1506
1500
            if index == 0:
1507
1501
                # Root node - special case
1511
1505
                    # The only case where we don't know the size, is for very
1512
1506
                    # small indexes. So we read the whole thing
1513
1507
                    bytes = self._transport.get_bytes(self._name)
1514
 
                    num_bytes = len(bytes)
1515
 
                    self._size = num_bytes - base_offset
 
1508
                    self._size = len(bytes)
1516
1509
                    # the whole thing should be parsed out of 'bytes'
1517
 
                    ranges = [(start, min(_PAGE_SIZE, num_bytes - start))
1518
 
                        for start in xrange(base_offset, num_bytes, _PAGE_SIZE)]
 
1510
                    ranges.append((0, len(bytes)))
1519
1511
                    break
1520
1512
            else:
1521
1513
                if offset > self._size:
1523
1515
                                         ' of the file %s > %s'
1524
1516
                                         % (offset, self._size))
1525
1517
                size = min(size, self._size - offset)
1526
 
            ranges.append((base_offset + offset, size))
 
1518
            ranges.append((offset, size))
1527
1519
        if not ranges:
1528
1520
            return
1529
1521
        elif bytes is not None:
1530
1522
            # already have the whole file
1531
 
            data_ranges = [(start, bytes[start:start+size])
1532
 
                           for start, size in ranges]
 
1523
            data_ranges = [(start, bytes[start:start+_PAGE_SIZE])
 
1524
                           for start in xrange(0, len(bytes), _PAGE_SIZE)]
1533
1525
        elif self._file is None:
1534
1526
            data_ranges = self._transport.readv(self._name, ranges)
1535
1527
        else:
1538
1530
                self._file.seek(offset)
1539
1531
                data_ranges.append((offset, self._file.read(size)))
1540
1532
        for offset, data in data_ranges:
1541
 
            offset -= base_offset
1542
1533
            if offset == 0:
1543
1534
                # extract the header
1544
1535
                offset, data = self._parse_header_from_bytes(data)