~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repofmt/pack_repo.py

  • Committer: John Arbash Meinel
  • Date: 2008-11-10 00:17:40 UTC
  • mto: This revision was merged to the branch mainline in revision 3866.
  • Revision ID: john@arbash-meinel.com-20081110001740-w1fd7io9lld9cvzf
Reorder the packs list after determining what packs
have the revisions we care about.

This saves us from reading text and inventory indexes that aren't
likely to have what we need.

Show diffs side-by-side

added added

removed removed

Lines of Context:
564
564
        # _copy_inventory_texts
565
565
        self._text_filter = None
566
566
        self._extra_init()
567
 
        self._pack_ordering = None
568
567
 
569
568
    def _extra_init(self):
570
569
        """A template hook to allow extending the constructor trivially."""
571
570
 
572
 
    def _packs_list_to_pack_map_and_index_list(self, packs, index_attribute):
 
571
    def _pack_map_and_index_list(self, index_attribute, include_pack_obj=False):
573
572
        """Convert a list of packs to an index pack map and index list.
574
573
 
575
 
        :param packs: The packs list to process.
576
574
        :param index_attribute: The attribute that the desired index is found
577
575
            on.
578
576
        :return: A tuple (map, list) where map contains the dict from
579
 
            index:pack_tuple, and lsit contains the indices in the same order
580
 
            as the packs list.
 
577
            index:pack_tuple, and lsit contains the indices in the preferred
 
578
            access order.
581
579
        """
582
580
        indices = []
583
581
        pack_map = {}
584
 
        for pack in packs:
585
 
            index = getattr(pack, index_attribute)
 
582
        for pack_obj in self.packs:
 
583
            index = getattr(pack_obj, index_attribute)
586
584
            indices.append(index)
587
 
            pack_map[index] = pack.access_tuple()
 
585
            pack_map[index] = pack_obj
588
586
        return pack_map, indices
589
587
 
590
 
    def _index_contents(self, pack_map, key_filter=None):
 
588
    def _index_contents(self, indices, key_filter=None):
591
589
        """Get an iterable of the index contents from a pack_map.
592
590
 
593
 
        :param pack_map: A map from indices to pack details.
594
 
        :param key_filter: An optional filter to limit the
595
 
            keys returned.
 
591
        :param indices: The list of indices to query
 
592
        :param key_filter: An optional filter to limit the keys returned.
596
593
        """
597
 
        indices = [index for index in pack_map.iterkeys()]
598
594
        all_index = CombinedGraphIndex(indices)
599
595
        if key_filter is None:
600
596
            return all_index.iter_all_entries()
649
645
            index_builder_class=self._pack_collection._index_builder_class,
650
646
            index_class=self._pack_collection._index_class)
651
647
 
 
648
    def _update_pack_order(self, entries, index_to_pack_map):
 
649
        """Determine how we want our packs to be ordered.
 
650
 
 
651
        This changes the sort order of self.packs, based on the order found in
 
652
        'entries'. This is mostly used to move unused packs to the end of the
 
653
        list, so that future requests can avoid probing them.
 
654
 
 
655
        :param entries: A list of (index, ...) tuples
 
656
        :param index_to_pack_map: A mapping from index objects to pack objects.
 
657
        """
 
658
        packs = []
 
659
        seen_indexes = set()
 
660
        for entry in entries:
 
661
            index = entry[0]
 
662
            if index not in seen_indexes:
 
663
                packs.append(index_to_pack_map[index])
 
664
                seen_indexes.add(index)
 
665
        if len(packs) == len(self.packs):
 
666
            if 'pack' in debug.debug_flags:
 
667
                mutter('Not changing pack list, all packs used.')
 
668
            return
 
669
        seen_packs = set(packs)
 
670
        for pack in self.packs:
 
671
            if pack not in seen_packs:
 
672
                packs.append(pack)
 
673
                seen_packs.add(pack)
 
674
        if 'pack' in debug.debug_flags:
 
675
            old_names = [p.access_tuple()[1] for p in self.packs]
 
676
            new_names = [p.access_tuple()[1] for p in packs]
 
677
            mutter('Reordering packs\nfrom: %s\n  to: %s',
 
678
                   old_names, new_names)
 
679
        self.packs = packs
 
680
 
652
681
    def _copy_revision_texts(self):
653
682
        """Copy revision data to the new pack."""
654
683
        # select revisions
657
686
        else:
658
687
            revision_keys = None
659
688
        # select revision keys
660
 
        revision_index_map = self._packs_list_to_pack_map_and_index_list(
661
 
            self.packs, 'revision_index')[0]
662
 
        revision_nodes = self._index_contents(revision_index_map, revision_keys)
 
689
        revision_index_map, revision_indices = self._pack_map_and_index_list(
 
690
            'revision_index')
 
691
        revision_nodes = self._index_contents(revision_indices, revision_keys)
 
692
        revision_nodes = list(revision_nodes)
 
693
        self._update_pack_order(revision_nodes, revision_index_map)
663
694
        # copy revision keys and adjust values
664
695
        self.pb.update("Copying revision texts", 1)
665
696
        total_items, readv_group_iter = self._revision_node_readv(revision_nodes)
685
716
        # querying for keys here could introduce a bug where an inventory item
686
717
        # is missed, so do not change it to query separately without cross
687
718
        # checking like the text key check below.
688
 
        inventory_index_map = self._packs_list_to_pack_map_and_index_list(
689
 
            self.packs, 'inventory_index')[0]
690
 
        inv_nodes = self._index_contents(inventory_index_map, inv_keys)
 
719
        inventory_index_map, inventory_indices = self._pack_map_and_index_list(
 
720
            'inventory_index')
 
721
        inv_nodes = self._index_contents(inventory_indices, inv_keys)
691
722
        # copy inventory keys and adjust values
692
723
        # XXX: Should be a helper function to allow different inv representation
693
724
        # at this point.
773
804
        self._copy_text_texts()
774
805
        # select signature keys
775
806
        signature_filter = self._revision_keys # same keyspace
776
 
        signature_index_map = self._packs_list_to_pack_map_and_index_list(
777
 
            self.packs, 'signature_index')[0]
778
 
        signature_nodes = self._index_contents(signature_index_map,
 
807
        signature_index_map, signature_indices = self._pack_map_and_index_list(
 
808
            'signature_index')
 
809
        signature_nodes = self._index_contents(signature_indices,
779
810
            signature_filter)
780
811
        # copy signature keys and adjust values
781
812
        self.pb.update("Copying signature texts", 4)
831
862
            # linear scan up the pack
832
863
            pack_readv_requests.sort()
833
864
            # copy the data
834
 
            transport, path = index_map[index]
 
865
            pack_obj = index_map[index]
 
866
            transport, path = pack_obj.access_tuple()
835
867
            reader = pack.make_readv_reader(transport, path,
836
868
                [offset[0:2] for offset in pack_readv_requests])
837
869
            for (names, read_func), (_1, _2, (key, eol_flag)) in \
875
907
        pb.update("Copied record", record_index, total_items)
876
908
        for index, readv_vector, node_vector in readv_group_iter:
877
909
            # copy the data
878
 
            transport, path = index_map[index]
 
910
            pack_obj = index_map[index]
 
911
            transport, path = pack_obj.access_tuple()
879
912
            reader = pack.make_readv_reader(transport, path, readv_vector)
880
913
            for (names, read_func), (key, eol_flag, references) in \
881
914
                izip(reader.iter_records(), node_vector):
899
932
                record_index += 1
900
933
 
901
934
    def _get_text_nodes(self):
902
 
        text_index_map = self._packs_list_to_pack_map_and_index_list(
903
 
            self.packs, 'text_index')[0]
904
 
        return text_index_map, self._index_contents(text_index_map,
 
935
        text_index_map, text_indices = self._pack_map_and_index_list(
 
936
            'text_index')
 
937
        return text_index_map, self._index_contents(text_indices,
905
938
            self._text_filter)
906
939
 
907
940
    def _least_readv_node_readv(self, nodes):
1252
1285
            return False
1253
1286
        # XXX: the following may want to be a class, to pack with a given
1254
1287
        # policy.
1255
 
        mutter('Auto-packing repository %s, which has %d pack files, '
1256
 
            'containing %d revisions into %d packs.', self, total_packs,
1257
 
            total_revisions, self._max_pack_count(total_revisions))
1258
1288
        # determine which packs need changing
1259
1289
        pack_distribution = self.pack_distribution(total_revisions)
1260
1290
        existing_packs = []
1275
1305
            existing_packs.append((revision_count, pack))
1276
1306
        pack_operations = self.plan_autopack_combinations(
1277
1307
            existing_packs, pack_distribution)
 
1308
        num_new_packs = len(pack_operations)
 
1309
        num_old_packs = sum([len(po[1]) for po in pack_operations])
 
1310
        num_revs_effected = sum([po[0] for po in pack_operations])
 
1311
        mutter('Auto-packing repository %s, which has %d pack files, '
 
1312
            'containing %d revisions. Packing %d files into %d effecting %d'
 
1313
            ' revisions', self, total_packs, total_revisions, num_old_packs,
 
1314
            num_new_packs, num_revs_effected)
1278
1315
        self._execute_pack_operations(pack_operations)
1279
1316
        return True
1280
1317