~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/__init__.py

  • Committer: Robert Collins
  • Date: 2005-10-17 01:40:24 UTC
  • mto: This revision was merged to the branch mainline in revision 1459.
  • Revision ID: robertc@lifelesslap.robertcollins.net-20051017014024-1c0d392828f918c3
Unroll the multiple-copy logic enough to remove the duplicate iteration and yet retain the optimised gzip->gzip copy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
102
102
        """
103
103
        if pb is None:
104
104
            pb = bzrlib.ui.ui_factory.progress_bar()
105
 
 
106
 
        # XXX: Is there any reason why we couldn't make this accept a generator
107
 
        # and build a list as it finds things to copy?
108
 
        ids = list(ids) # Make sure we don't have a generator, since we iterate 2 times
109
105
        pb.update('preparing to copy')
110
 
        to_copy = []
111
 
        for file_id in ids:
112
 
            if not self.has_id(file_id):
113
 
                to_copy.append(file_id)
114
 
        return self._do_copy(other, to_copy, pb, permit_failure=permit_failure)
115
 
 
116
 
    def _do_copy(self, other, to_copy, pb, permit_failure=False):
117
 
        """This is the standard copying mechanism, just get them one at
118
 
        a time from remote, and store them locally.
119
 
 
120
 
        :param other: Another Store object
121
 
        :param to_copy: A list of entry ids to copy
122
 
        :param pb: A ProgressBar object to display completion status.
123
 
        :param permit_failure: Allow missing entries to be ignored
124
 
        :return: (n_copied, [failed])
125
 
            The number of entries copied, and a list of failed entries.
126
 
        """
127
 
        # This should be updated to use add_multi() rather than
128
 
        # the current methods of buffering requests.
129
 
        # One question, is it faster to queue up 1-10 and then copy 1-10
130
 
        # then queue up 11-20, copy 11-20
131
 
        # or to queue up 1-10, copy 1, queue 11, copy 2, etc?
132
 
        # sort of pipeline versus batch.
133
 
 
134
 
        # We can't use self._transport.copy_to because we don't know
135
 
        # whether the local tree is in the same format as other
136
106
        failed = set()
137
 
        def buffer_requests():
138
 
            count = 0
139
 
            buffered_requests = []
140
 
            for fileid in to_copy:
141
 
                try:
142
 
                    f = other.get(fileid)
143
 
                except KeyError:
144
 
                    if permit_failure:
145
 
                        failed.add(fileid)
146
 
                        continue
147
 
                    else:
148
 
                        raise
149
 
 
150
 
                buffered_requests.append((f, fileid))
151
 
                if len(buffered_requests) > self._max_buffered_requests:
152
 
                    yield buffered_requests.pop(0)
153
 
                    count += 1
154
 
                    pb.update('copy', count, len(to_copy))
155
 
 
156
 
            for req in buffered_requests:
157
 
                yield req
158
 
                count += 1
159
 
                pb.update('copy', count, len(to_copy))
160
 
 
161
 
            assert count == len(to_copy)
162
 
 
163
 
        for f, fileid in buffer_requests():
164
 
            self.add(f, fileid)
165
 
 
 
107
        count = 0
 
108
        ids = list(ids) # get the list for showing a length.
 
109
        for fileid in ids:
 
110
            count += 1
 
111
            if self.has_id(fileid):
 
112
                continue
 
113
            try:
 
114
                self._copy_one(fileid, other, pb)
 
115
                pb.update('copy', count, len(ids))
 
116
            except KeyError:
 
117
                if permit_failure:
 
118
                    failed.add(fileid)
 
119
                else:
 
120
                    raise
 
121
        assert count == len(ids)
166
122
        pb.clear()
167
 
        return len(to_copy), failed
 
123
        return count, failed
 
124
 
 
125
    def _copy_one(self, fileid, other, pb):
 
126
        """Most generic copy-one object routine.
 
127
        
 
128
        Subclasses can override this to provide an optimised
 
129
        copy between their own instances. Such overriden routines
 
130
        should call this if they have no optimised facility for a 
 
131
        specific 'other'.
 
132
        """
 
133
        f = other.get(fileid)
 
134
        self.add(f, fileid)
168
135
 
169
136
 
170
137
class TransportStore(Store):
171
138
    """A TransportStore is a Store superclass for Stores that use Transports."""
172
139
 
173
 
    _max_buffered_requests = 10
174
 
 
175
140
    def add(self, f, fileid, suffix=None):
176
141
        """Add contents of a file into the store.
177
142