~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/pack_repo.py

  • Committer: Andrew Bennetts
  • Date: 2011-03-24 00:13:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5739.
  • Revision ID: andrew.bennetts@canonical.com-20110324001310-5w56qjom53j091r3
Minor English tweaks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
""")
50
50
from bzrlib import (
51
51
    bzrdir,
 
52
    btree_index,
52
53
    errors,
53
54
    lockable_files,
54
55
    lockdir,
56
57
    )
57
58
 
58
59
from bzrlib.decorators import needs_write_lock, only_raises
59
 
from bzrlib.btree_index import (
60
 
    BTreeGraphIndex,
61
 
    BTreeBuilder,
62
 
    )
63
60
from bzrlib.index import (
64
61
    GraphIndex,
65
62
    InMemoryGraphIndex,
231
228
        unlimited_cache = False
232
229
        if index_type == 'chk':
233
230
            unlimited_cache = True
234
 
        setattr(self, index_type + '_index',
235
 
            self.index_class(self.index_transport,
236
 
                self.index_name(index_type, self.name),
237
 
                self.index_sizes[self.index_offset(index_type)],
238
 
                unlimited_cache=unlimited_cache))
 
231
        index = self.index_class(self.index_transport,
 
232
                    self.index_name(index_type, self.name),
 
233
                    self.index_sizes[self.index_offset(index_type)],
 
234
                    unlimited_cache=unlimited_cache)
 
235
        if index_type == 'chk':
 
236
            index._leaf_factory = btree_index._gcchk_factory
 
237
        setattr(self, index_type + '_index', index)
239
238
 
240
239
 
241
240
class ExistingPack(Pack):
723
722
        :return: A Pack object, or None if nothing was copied.
724
723
        """
725
724
        # open a pack - using the same name as the last temporary file
726
 
        # - which has already been flushed, so its safe.
 
725
        # - which has already been flushed, so it's safe.
727
726
        # XXX: - duplicate code warning with start_write_group; fix before
728
727
        #      considering 'done'.
729
728
        if self._pack_collection._new_pack is not None:
1223
1222
    def _process_inventory_lines(self, inv_lines):
1224
1223
        """Generate a text key reference map rather for reconciling with."""
1225
1224
        repo = self._pack_collection.repo
1226
 
        refs = repo._find_text_key_references_from_xml_inventory_lines(
1227
 
            inv_lines)
 
1225
        refs = repo._serializer._find_text_key_references(inv_lines)
1228
1226
        self._text_refs = refs
1229
1227
        # during reconcile we:
1230
1228
        #  - convert unreferenced texts to full texts
1293
1291
        # reinserted, and if d3 has incorrect parents it will also be
1294
1292
        # reinserted. If we insert d3 first, d2 is present (as it was bulk
1295
1293
        # copied), so we will try to delta, but d2 is not currently able to be
1296
 
        # extracted because it's basis d1 is not present. Topologically sorting
 
1294
        # extracted because its basis d1 is not present. Topologically sorting
1297
1295
        # addresses this. The following generates a sort for all the texts that
1298
1296
        # are being inserted without having to reference the entire text key
1299
1297
        # space (we only topo sort the revisions, which is smaller).
1574
1572
        mutter('Packing repository %s, which has %d pack files, '
1575
1573
            'containing %d revisions with hint %r.', self, total_packs,
1576
1574
            total_revisions, hint)
 
1575
        while True:
 
1576
            try:
 
1577
                self._try_pack_operations(hint)
 
1578
            except RetryPackOperations:
 
1579
                continue
 
1580
            break
 
1581
 
 
1582
        if clean_obsolete_packs:
 
1583
            self._clear_obsolete_packs()
 
1584
 
 
1585
    def _try_pack_operations(self, hint):
 
1586
        """Calculate the pack operations based on the hint (if any), and
 
1587
        execute them.
 
1588
        """
1577
1589
        # determine which packs need changing
1578
1590
        pack_operations = [[0, []]]
1579
1591
        for pack in self.all_packs():
1582
1594
                # or this pack was included in the hint.
1583
1595
                pack_operations[-1][0] += pack.get_revision_count()
1584
1596
                pack_operations[-1][1].append(pack)
1585
 
        self._execute_pack_operations(pack_operations, OptimisingPacker)
1586
 
 
1587
 
        if clean_obsolete_packs:
1588
 
            self._clear_obsolete_packs()
 
1597
        self._execute_pack_operations(pack_operations, OptimisingPacker,
 
1598
            reload_func=self._restart_pack_operations)
1589
1599
 
1590
1600
    def plan_autopack_combinations(self, existing_packs, pack_distribution):
1591
1601
        """Plan a pack operation.
1601
1611
        pack_operations = [[0, []]]
1602
1612
        # plan out what packs to keep, and what to reorganise
1603
1613
        while len(existing_packs):
1604
 
            # take the largest pack, and if its less than the head of the
 
1614
            # take the largest pack, and if it's less than the head of the
1605
1615
            # distribution chart we will include its contents in the new pack
1606
 
            # for that position. If its larger, we remove its size from the
 
1616
            # for that position. If it's larger, we remove its size from the
1607
1617
            # distribution chart
1608
1618
            next_pack_rev_count, next_pack = existing_packs.pop(0)
1609
1619
            if next_pack_rev_count >= pack_distribution[0]:
1644
1654
 
1645
1655
        :return: True if the disk names had not been previously read.
1646
1656
        """
1647
 
        # NB: if you see an assertion error here, its probably access against
 
1657
        # NB: if you see an assertion error here, it's probably access against
1648
1658
        # an unlocked repo. Naughty.
1649
1659
        if not self.repo.is_locked():
1650
1660
            raise errors.ObjectNotLocked(self.repo)
1680
1690
            txt_index = self._make_index(name, '.tix')
1681
1691
            sig_index = self._make_index(name, '.six')
1682
1692
            if self.chk_index is not None:
1683
 
                chk_index = self._make_index(name, '.cix', unlimited_cache=True)
 
1693
                chk_index = self._make_index(name, '.cix', is_chk=True)
1684
1694
            else:
1685
1695
                chk_index = None
1686
1696
            result = ExistingPack(self._pack_transport, name, rev_index,
1706
1716
            sig_index = self._make_index(name, '.six', resume=True)
1707
1717
            if self.chk_index is not None:
1708
1718
                chk_index = self._make_index(name, '.cix', resume=True,
1709
 
                                             unlimited_cache=True)
 
1719
                                             is_chk=True)
1710
1720
            else:
1711
1721
                chk_index = None
1712
1722
            result = self.resumed_pack_factory(name, rev_index, inv_index,
1742
1752
        return self._index_class(self.transport, 'pack-names', None
1743
1753
                ).iter_all_entries()
1744
1754
 
1745
 
    def _make_index(self, name, suffix, resume=False, unlimited_cache=False):
 
1755
    def _make_index(self, name, suffix, resume=False, is_chk=False):
1746
1756
        size_offset = self._suffix_offsets[suffix]
1747
1757
        index_name = name + suffix
1748
1758
        if resume:
1751
1761
        else:
1752
1762
            transport = self._index_transport
1753
1763
            index_size = self._names[name][size_offset]
1754
 
        return self._index_class(transport, index_name, index_size,
1755
 
                                 unlimited_cache=unlimited_cache)
 
1764
        index = self._index_class(transport, index_name, index_size,
 
1765
                                  unlimited_cache=is_chk)
 
1766
        if is_chk and self._index_class is btree_index.BTreeGraphIndex: 
 
1767
            index._leaf_factory = btree_index._gcchk_factory
 
1768
        return index
1756
1769
 
1757
1770
    def _max_pack_count(self, total_revisions):
1758
1771
        """Return the maximum number of packs to use for total revisions.
1944
1957
                    # disk index because the set values are the same, unless
1945
1958
                    # the only index shows up as deleted by the set difference
1946
1959
                    # - which it may. Until there is a specific test for this,
1947
 
                    # assume its broken. RBC 20071017.
 
1960
                    # assume it's broken. RBC 20071017.
1948
1961
                    self._remove_pack_from_memory(self.get_pack_by_name(name))
1949
1962
                    self._names[name] = sizes
1950
1963
                    self.get_pack_by_name(name)
2015
2028
        """
2016
2029
        # The ensure_loaded call is to handle the case where the first call
2017
2030
        # made involving the collection was to reload_pack_names, where we 
2018
 
        # don't have a view of disk contents. Its a bit of a bandaid, and
2019
 
        # causes two reads of pack-names, but its a rare corner case not struck
2020
 
        # with regular push/pull etc.
 
2031
        # don't have a view of disk contents. It's a bit of a bandaid, and
 
2032
        # causes two reads of pack-names, but it's a rare corner case not
 
2033
        # struck with regular push/pull etc.
2021
2034
        first_read = self.ensure_loaded()
2022
2035
        if first_read:
2023
2036
            return True
2042
2055
            raise
2043
2056
        raise errors.RetryAutopack(self.repo, False, sys.exc_info())
2044
2057
 
 
2058
    def _restart_pack_operations(self):
 
2059
        """Reload the pack names list, and restart the autopack code."""
 
2060
        if not self.reload_pack_names():
 
2061
            # Re-raise the original exception, because something went missing
 
2062
            # and a restart didn't find it
 
2063
            raise
 
2064
        raise RetryPackOperations(self.repo, False, sys.exc_info())
 
2065
 
2045
2066
    def _clear_obsolete_packs(self, preserve=None):
2046
2067
        """Delete everything from the obsolete-packs directory.
2047
2068
 
2282
2303
        self._reconcile_fixes_text_parents = True
2283
2304
        self._reconcile_backsup_inventory = False
2284
2305
 
2285
 
    def _warn_if_deprecated(self, branch=None):
2286
 
        # This class isn't deprecated, but one sub-format is
2287
 
        if isinstance(self._format, RepositoryFormatKnitPack5RichRootBroken):
2288
 
            super(KnitPackRepository, self)._warn_if_deprecated(branch)
2289
 
 
2290
2306
    def _abort_write_group(self):
2291
2307
        self.revisions._index._key_dependencies.clear()
2292
2308
        self._pack_collection._abort_write_group()
2454
2470
        from_repo = self.from_repository
2455
2471
        parent_ids = from_repo._find_parent_ids_of_revisions(revision_ids)
2456
2472
        parent_keys = [(p,) for p in parent_ids]
2457
 
        find_text_keys = from_repo._find_text_key_references_from_xml_inventory_lines
 
2473
        find_text_keys = from_repo._serializer._find_text_key_references
2458
2474
        parent_text_keys = set(find_text_keys(
2459
2475
            from_repo._inventory_xml_lines_for_keys(parent_keys)))
2460
2476
        content_text_keys = set()
2542
2558
    index_class = None
2543
2559
    _fetch_uses_deltas = True
2544
2560
    fast_deltas = False
 
2561
    supports_full_versioned_files = True
 
2562
    supports_funky_characters = True
2545
2563
 
2546
2564
    def initialize(self, a_bzrdir, shared=False):
2547
2565
        """Create a pack based repository.
2817
2835
        return ("Packs 5 rich-root (adds stacking support, requires bzr 1.6)"
2818
2836
                " (deprecated)")
2819
2837
 
 
2838
    def is_deprecated(self):
 
2839
        return True
 
2840
 
2820
2841
 
2821
2842
class RepositoryFormatKnitPack6(RepositoryFormatPack):
2822
2843
    """A repository with stacking and btree indexes,
2829
2850
    _commit_builder_class = PackCommitBuilder
2830
2851
    supports_external_lookups = True
2831
2852
    # What index classes to use
2832
 
    index_builder_class = BTreeBuilder
2833
 
    index_class = BTreeGraphIndex
 
2853
    index_builder_class = btree_index.BTreeBuilder
 
2854
    index_class = btree_index.BTreeGraphIndex
2834
2855
 
2835
2856
    @property
2836
2857
    def _serializer(self):
2865
2886
    supports_tree_reference = False # no subtrees
2866
2887
    supports_external_lookups = True
2867
2888
    # What index classes to use
2868
 
    index_builder_class = BTreeBuilder
2869
 
    index_class = BTreeGraphIndex
 
2889
    index_builder_class = btree_index.BTreeBuilder
 
2890
    index_class = btree_index.BTreeGraphIndex
2870
2891
 
2871
2892
    @property
2872
2893
    def _serializer(self):
2892
2913
class RepositoryFormatPackDevelopment2Subtree(RepositoryFormatPack):
2893
2914
    """A subtrees development repository.
2894
2915
 
2895
 
    This format should be retained until the second release after bzr 1.7.
 
2916
    This format should be retained in 2.3, to provide an upgrade path from this
 
2917
    to RepositoryFormat2aSubtree.  It can be removed in later releases.
2896
2918
 
2897
2919
    1.6.1-subtree[as it might have been] with B+Tree indices.
2898
 
 
2899
 
    This is [now] retained until we have a CHK based subtree format in
2900
 
    development.
2901
2920
    """
2902
2921
 
2903
2922
    repository_class = KnitPackRepository
2907
2926
    supports_tree_reference = True
2908
2927
    supports_external_lookups = True
2909
2928
    # What index classes to use
2910
 
    index_builder_class = BTreeBuilder
2911
 
    index_class = BTreeGraphIndex
 
2929
    index_builder_class = btree_index.BTreeBuilder
 
2930
    index_class = btree_index.BTreeGraphIndex
2912
2931
 
2913
2932
    @property
2914
2933
    def _serializer(self):
2916
2935
 
2917
2936
    def _get_matching_bzrdir(self):
2918
2937
        return bzrdir.format_registry.make_bzrdir(
2919
 
            'development-subtree')
 
2938
            'development5-subtree')
2920
2939
 
2921
2940
    def _ignore_setting_bzrdir(self, format):
2922
2941
        pass
2933
2952
        return ("Development repository format, currently the same as "
2934
2953
            "1.6.1-subtree with B+Tree indices.\n")
2935
2954
 
 
2955
 
 
2956
class RetryPackOperations(errors.RetryWithNewPacks):
 
2957
    """Raised when we are packing and we find a missing file.
 
2958
 
 
2959
    Meant as a signaling exception, to tell the RepositoryPackCollection.pack
 
2960
    code it should try again.
 
2961
    """
 
2962
 
 
2963
    internal_error = True
 
2964
 
 
2965
    _fmt = ("Pack files have changed, reload and try pack again."
 
2966
            " context: %(context)s %(orig_error)s")
 
2967
 
 
2968