~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: John Arbash Meinel
  • Date: 2010-09-21 19:30:33 UTC
  • mto: This revision was merged to the branch mainline in revision 5451.
  • Revision ID: john@arbash-meinel.com-20100921193033-9ftw56og72mhlwo4
Change GroupCompressBlock to work in self._z_compress_chunks

This pushes down one of the peak memory locations. We still have a requirement
during commit of 1 fulltext + 2 compressed texts, but at least this code
path is now better about only using 1 fulltext and 1 compressed text.
We need to push this into more apis to get a bigger benefit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    check,
26
26
    chk_map,
27
27
    config,
 
28
    controldir,
28
29
    debug,
29
 
    errors,
30
30
    fetch as _mod_fetch,
31
31
    fifo_cache,
32
32
    generate_ids,
44
44
    symbol_versioning,
45
45
    trace,
46
46
    tsort,
47
 
    ui,
48
47
    versionedfile,
49
48
    )
50
49
from bzrlib.bundle import serializer
53
52
from bzrlib.testament import Testament
54
53
""")
55
54
 
 
55
from bzrlib import (
 
56
    errors,
 
57
    registry,
 
58
    ui,
 
59
    )
56
60
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
57
61
from bzrlib.inter import InterObject
58
62
from bzrlib.inventory import (
61
65
    ROOT_ID,
62
66
    entry_factory,
63
67
    )
64
 
from bzrlib.lock import _RelockDebugMixin
65
 
from bzrlib import registry
 
68
from bzrlib.recordcounter import RecordCounter
 
69
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
66
70
from bzrlib.trace import (
67
71
    log_exception_quietly, note, mutter, mutter_callsite, warning)
68
72
 
71
75
_deprecation_warning_done = False
72
76
 
73
77
 
 
78
class IsInWriteGroupError(errors.InternalBzrError):
 
79
 
 
80
    _fmt = "May not refresh_data of repo %(repo)s while in a write group."
 
81
 
 
82
    def __init__(self, repo):
 
83
        errors.InternalBzrError.__init__(self, repo=repo)
 
84
 
 
85
 
74
86
class CommitBuilder(object):
75
87
    """Provides an interface to build up a commit.
76
88
 
231
243
 
232
244
    def _gen_revision_id(self):
233
245
        """Return new revision-id."""
234
 
        return generate_ids.gen_revision_id(self._config.username(),
235
 
                                            self._timestamp)
 
246
        return generate_ids.gen_revision_id(self._committer, self._timestamp)
236
247
 
237
248
    def _generate_revision_if_needed(self):
238
249
        """Create a revision id if None was supplied.
278
289
 
279
290
        :param tree: The tree which is being committed.
280
291
        """
281
 
        # NB: if there are no parents then this method is not called, so no
282
 
        # need to guard on parents having length.
 
292
        if len(self.parents) == 0:
 
293
            raise errors.RootMissing()
283
294
        entry = entry_factory['directory'](tree.path2id(''), '',
284
295
            None)
285
296
        entry.revision = self._new_revision_id
860
871
        # versioned roots do not change unless the tree found a change.
861
872
 
862
873
 
863
 
class RepositoryWriteLockResult(object):
 
874
class RepositoryWriteLockResult(LogicalLockResult):
864
875
    """The result of write locking a repository.
865
876
 
866
877
    :ivar repository_token: The token obtained from the underlying lock, or
869
880
    """
870
881
 
871
882
    def __init__(self, unlock, repository_token):
 
883
        LogicalLockResult.__init__(self, unlock)
872
884
        self.repository_token = repository_token
873
 
        self.unlock = unlock
874
885
 
875
 
    def __str__(self):
 
886
    def __repr__(self):
876
887
        return "RepositoryWriteLockResult(%s, %s)" % (self.repository_token,
877
888
            self.unlock)
878
889
 
881
892
# Repositories
882
893
 
883
894
 
884
 
class Repository(_RelockDebugMixin, bzrdir.ControlComponent):
 
895
class Repository(_RelockDebugMixin, controldir.ControlComponent):
885
896
    """Repository holding history for one or more branches.
886
897
 
887
898
    The repository holds and retrieves historical information including
1035
1046
                " id and insertion revid (%r, %r)"
1036
1047
                % (inv.revision_id, revision_id))
1037
1048
        if inv.root is None:
1038
 
            raise AssertionError()
 
1049
            raise errors.RootMissing()
1039
1050
        return self._add_inventory_checked(revision_id, inv, parents)
1040
1051
 
1041
1052
    def _add_inventory_checked(self, revision_id, inv, parents):
1434
1445
            for repo in self._fallback_repositories:
1435
1446
                repo.lock_read()
1436
1447
            self._refresh_data()
1437
 
        return self
 
1448
        return LogicalLockResult(self.unlock)
1438
1449
 
1439
1450
    def get_physical_lock_status(self):
1440
1451
        return self.control_files.get_physical_lock_status()
1658
1669
        return missing_keys
1659
1670
 
1660
1671
    def refresh_data(self):
1661
 
        """Re-read any data needed to to synchronise with disk.
 
1672
        """Re-read any data needed to synchronise with disk.
1662
1673
 
1663
1674
        This method is intended to be called after another repository instance
1664
1675
        (such as one used by a smart server) has inserted data into the
1665
 
        repository. It may not be called during a write group, but may be
1666
 
        called at any other time.
 
1676
        repository. On all repositories this will work outside of write groups.
 
1677
        Some repository formats (pack and newer for bzrlib native formats)
 
1678
        support refresh_data inside write groups. If called inside a write
 
1679
        group on a repository that does not support refreshing in a write group
 
1680
        IsInWriteGroupError will be raised.
1667
1681
        """
1668
 
        if self.is_in_write_group():
1669
 
            raise errors.InternalBzrError(
1670
 
                "May not refresh_data while in a write group.")
1671
1682
        self._refresh_data()
1672
1683
 
1673
1684
    def resume_write_group(self, tokens):
1712
1723
                "May not fetch while in a write group.")
1713
1724
        # fast path same-url fetch operations
1714
1725
        # TODO: lift out to somewhere common with RemoteRepository
1715
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/401646>
 
1726
        # <https://bugs.launchpad.net/bzr/+bug/401646>
1716
1727
        if (self.has_same_location(source)
1717
1728
            and fetch_spec is None
1718
1729
            and self._has_same_fallbacks(source)):
3378
3389
    'bzrlib.repofmt.groupcompress_repo',
3379
3390
    'RepositoryFormat2a',
3380
3391
    )
 
3392
format_registry.register_lazy(
 
3393
    'Bazaar development format 8\n',
 
3394
    'bzrlib.repofmt.groupcompress_repo',
 
3395
    'RepositoryFormat2aSubtree',
 
3396
    )
3381
3397
 
3382
3398
 
3383
3399
class InterRepository(InterObject):
3837
3853
                basis_id, delta, current_revision_id, parents_parents)
3838
3854
            cache[current_revision_id] = parent_tree
3839
3855
 
3840
 
    def _fetch_batch(self, revision_ids, basis_id, cache, a_graph=None):
 
3856
    def _fetch_batch(self, revision_ids, basis_id, cache):
3841
3857
        """Fetch across a few revisions.
3842
3858
 
3843
3859
        :param revision_ids: The revisions to copy
3844
3860
        :param basis_id: The revision_id of a tree that must be in cache, used
3845
3861
            as a basis for delta when no other base is available
3846
3862
        :param cache: A cache of RevisionTrees that we can use.
3847
 
        :param a_graph: A Graph object to determine the heads() of the
3848
 
            rich-root data stream.
3849
3863
        :return: The revision_id of the last converted tree. The RevisionTree
3850
3864
            for it will be in cache
3851
3865
        """
3919
3933
        if root_keys_to_create:
3920
3934
            root_stream = _mod_fetch._new_root_data_stream(
3921
3935
                root_keys_to_create, self._revision_id_to_root_id, parent_map,
3922
 
                self.source, graph=a_graph)
 
3936
                self.source)
3923
3937
            to_texts.insert_record_stream(root_stream)
3924
3938
        to_texts.insert_record_stream(from_texts.get_record_stream(
3925
3939
            text_keys, self.target._format._fetch_order,
3982
3996
        cache[basis_id] = basis_tree
3983
3997
        del basis_tree # We don't want to hang on to it here
3984
3998
        hints = []
3985
 
        if self._converting_to_rich_root and len(revision_ids) > 100:
3986
 
            a_graph = _mod_fetch._get_rich_root_heads_graph(self.source,
3987
 
                                                            revision_ids)
3988
 
        else:
3989
 
            a_graph = None
 
3999
        a_graph = None
3990
4000
 
3991
4001
        for offset in range(0, len(revision_ids), batch_size):
3992
4002
            self.target.start_write_group()
3994
4004
                pb.update('Transferring revisions', offset,
3995
4005
                          len(revision_ids))
3996
4006
                batch = revision_ids[offset:offset+batch_size]
3997
 
                basis_id = self._fetch_batch(batch, basis_id, cache,
3998
 
                                             a_graph=a_graph)
 
4007
                basis_id = self._fetch_batch(batch, basis_id, cache)
3999
4008
            except:
4000
4009
                self.source._safe_to_return_from_cache = False
4001
4010
                self.target.abort_write_group()
4273
4282
                is_resume = False
4274
4283
            try:
4275
4284
                # locked_insert_stream performs a commit|suspend.
4276
 
                return self._locked_insert_stream(stream, src_format, is_resume)
 
4285
                return self._locked_insert_stream(stream, src_format,
 
4286
                    is_resume)
4277
4287
            except:
4278
4288
                self.target_repo.abort_write_group(suppress_errors=True)
4279
4289
                raise
4326
4336
                # required if the serializers are different only in terms of
4327
4337
                # the inventory.
4328
4338
                if src_serializer == to_serializer:
4329
 
                    self.target_repo.revisions.insert_record_stream(
4330
 
                        substream)
 
4339
                    self.target_repo.revisions.insert_record_stream(substream)
4331
4340
                else:
4332
4341
                    self._extract_and_insert_revisions(substream,
4333
4342
                        src_serializer)
4441
4450
        """Create a StreamSource streaming from from_repository."""
4442
4451
        self.from_repository = from_repository
4443
4452
        self.to_format = to_format
 
4453
        self._record_counter = RecordCounter()
4444
4454
 
4445
4455
    def delta_on_metadata(self):
4446
4456
        """Return True if delta's are permitted on metadata streams.