~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/__init__.py

Merge a recent bzr.dev (2172) and takes John's remarks into account.

Show diffs side-by-side

added added

removed removed

Lines of Context:
250
250
        """
251
251
        return self
252
252
 
 
253
    def _retry_get(self, relpath, ranges, exc_info):
 
254
        """A GET request have failed, let's retry with a simpler request."""
 
255
 
 
256
        try_again = False
 
257
        # The server does not gives us enough data or
 
258
        # bogus-looking result, let's try again with
 
259
        # a simpler request if possible.
 
260
        if self._range_hint == 'multi':
 
261
            self._range_hint = 'single'
 
262
            mutter('Retry %s with single range request' % relpath)
 
263
            try_again = True
 
264
        elif self._range_hint == 'single':
 
265
            self._range_hint = None
 
266
            mutter('Retry %s without ranges' % relpath)
 
267
            try_again = True
 
268
        if try_again:
 
269
            # Note that since the offsets and the ranges may not
 
270
            # be in the same order we dont't try to calculate a
 
271
            # restricted single range encompassing unprocessed
 
272
            # offsets.
 
273
            code, f = self._get(relpath, ranges)
 
274
            return try_again, code, f
 
275
        else:
 
276
            # We tried all the tricks, nothing worked
 
277
            raise exc_info[0], exc_info[1], exc_info[2]
 
278
 
253
279
    def readv(self, relpath, offsets):
254
280
        """Get parts of the file at the given relative path.
255
281
 
259
285
        ranges = self.offsets_to_ranges(offsets)
260
286
        mutter('http readv of %s collapsed %s offsets => %s',
261
287
                relpath, len(offsets), ranges)
262
 
        code, f = self._get(relpath, ranges)
 
288
 
 
289
        try_again = True
 
290
        while try_again:
 
291
            try_again = False
 
292
            try:
 
293
                code, f = self._get(relpath, ranges)
 
294
            except (errors.InvalidRange, errors.ShortReadvError), e:
 
295
                try_again, code, f = self._retry_get(relpath, ranges,
 
296
                                                     sys.exc_info())
 
297
 
263
298
        for start, size in offsets:
264
299
            try_again = True
265
300
            while try_again:
271
306
                    if len(data) != size:
272
307
                        raise errors.ShortReadvError(relpath, start, size,
273
308
                                                     actual=len(data))
274
 
                except (errors.InvalidRange, errors.ShortReadvError):
275
 
                    # The server does not gives us enough data or
276
 
                    # bogus-looking result, let's try again with
277
 
                    # a simpler request if possible.
278
 
                    if self._range_hint == 'multi':
279
 
                        self._range_hint = 'single'
280
 
                        mutter('Retry %s with single range request' % relpath)
281
 
                        try_again = True
282
 
                    elif self._range_hint == 'single':
283
 
                        self._range_hint = None
284
 
                        mutter('Retry %s without ranges' % relpath)
285
 
                        try_again = True
286
 
                    if try_again:
287
 
                        # Note that since the offsets and the
288
 
                        # ranges may not be in the same order we
289
 
                        # dont't try to calculate a restricted
290
 
                        # single range encompassing unprocessed
291
 
                        # offsets. Note that we replace 'f' here
292
 
                        # and that it may need cleaning one day
293
 
                        # before being thrown that way.
294
 
                        code, f = self._get(relpath, ranges)
295
 
                    else:
296
 
                        # We tried all the tricks, nothing worked
297
 
                        raise
298
 
 
 
309
                except (errors.InvalidRange, errors.ShortReadvError), e:
 
310
                    # Note that we replace 'f' here and that it
 
311
                    # may need cleaning one day before being
 
312
                    # thrown that way.
 
313
                    try_again, code, f = self._retry_get(relpath, ranges,
 
314
                                                         sys.exc_info())
 
315
            # After one or more tries, we get the data.
299
316
            yield start, data
300
317
 
301
318
    @staticmethod