/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/remote.py

  • Committer: Andrew Bennetts
  • Date: 2008-11-27 06:29:56 UTC
  • mfrom: (3861 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3863.
  • Revision ID: andrew.bennetts@canonical.com-20081127062956-v0a19icwk85iosx4
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
61
61
    RemoteTCPTransport, etc.
62
62
    """
63
63
 
 
64
    # When making a readv request, cap it at requesting 5MB of data
 
65
    _max_readv_bytes = 5*1024*1024
 
66
 
64
67
    # IMPORTANT FOR IMPLEMENTORS: RemoteTransport MUST NOT be given encoding
65
68
    # responsibilities: Put those on SmartClient or similar. This is vital for
66
69
    # the ability to support multiple versions of the smart protocol over time:
169
172
        try:
170
173
            return self._client.call(method, *args)
171
174
        except errors.ErrorFromSmartServer, err:
172
 
            self._translate_error(err)
 
175
            # The first argument, if present, is always a path.
 
176
            if args:
 
177
                context = {'relpath': args[0]}
 
178
            else:
 
179
                context = {}
 
180
            self._translate_error(err, **context)
173
181
 
174
182
    def _call_with_body_bytes(self, method, args, body):
175
183
        """Call a method on the remote server with body bytes."""
176
184
        try:
177
185
            return self._client.call_with_body_bytes(method, args, body)
178
186
        except errors.ErrorFromSmartServer, err:
179
 
            self._translate_error(err)
 
187
            # The first argument, if present, is always a path.
 
188
            if args:
 
189
                context = {'relpath': args[0]}
 
190
            else:
 
191
                context = {}
 
192
            self._translate_error(err, **context)
180
193
 
181
194
    def has(self, relpath):
182
195
        """Indicate whether a remote file of the given name exists or not.
312
325
                               limit=self._max_readv_combine,
313
326
                               fudge_factor=self._bytes_to_read_before_seek))
314
327
 
315
 
        try:
316
 
            result = self._client.call_with_body_readv_array(
317
 
                ('readv', self._remote_path(relpath),),
318
 
                [(c.start, c.length) for c in coalesced])
319
 
            resp, response_handler = result
320
 
        except errors.ErrorFromSmartServer, err:
321
 
            self._translate_error(err)
322
 
 
323
 
        if resp[0] != 'readv':
324
 
            # This should raise an exception
325
 
            response_handler.cancel_read_body()
326
 
            raise errors.UnexpectedSmartServerResponse(resp)
327
 
 
328
 
        return self._handle_response(offsets, coalesced, response_handler)
329
 
 
330
 
    def _handle_response(self, offsets, coalesced, response_handler):
331
 
        # turn the list of offsets into a stack
 
328
        # now that we've coallesced things, avoid making enormous requests
 
329
        requests = []
 
330
        cur_request = []
 
331
        cur_len = 0
 
332
        for c in coalesced:
 
333
            if c.length + cur_len > self._max_readv_bytes:
 
334
                requests.append(cur_request)
 
335
                cur_request = [c]
 
336
                cur_len = c.length
 
337
                continue
 
338
            cur_request.append(c)
 
339
            cur_len += c.length
 
340
        if cur_request:
 
341
            requests.append(cur_request)
 
342
        if 'hpss' in debug.debug_flags:
 
343
            trace.mutter('%s.readv %s offsets => %s coalesced'
 
344
                         ' => %s requests (%s)',
 
345
                         self.__class__.__name__, len(offsets), len(coalesced),
 
346
                         len(requests), sum(map(len, requests)))
 
347
        # Cache the results, but only until they have been fulfilled
 
348
        data_map = {}
 
349
        # turn the list of offsets into a single stack to iterate
332
350
        offset_stack = iter(offsets)
333
 
        cur_offset_and_size = offset_stack.next()
 
351
        # using a list so it can be modified when passing down and coming back
 
352
        next_offset = [offset_stack.next()]
 
353
        for cur_request in requests:
 
354
            try:
 
355
                result = self._client.call_with_body_readv_array(
 
356
                    ('readv', self._remote_path(relpath),),
 
357
                    [(c.start, c.length) for c in cur_request])
 
358
                resp, response_handler = result
 
359
            except errors.ErrorFromSmartServer, err:
 
360
                self._translate_error(err, relpath)
 
361
 
 
362
            if resp[0] != 'readv':
 
363
                # This should raise an exception
 
364
                response_handler.cancel_read_body()
 
365
                raise errors.UnexpectedSmartServerResponse(resp)
 
366
 
 
367
            for res in self._handle_response(offset_stack, cur_request,
 
368
                                             response_handler,
 
369
                                             data_map,
 
370
                                             next_offset):
 
371
                yield res
 
372
 
 
373
    def _handle_response(self, offset_stack, coalesced, response_handler,
 
374
                         data_map, next_offset):
 
375
        cur_offset_and_size = next_offset[0]
334
376
        # FIXME: this should know how many bytes are needed, for clarity.
335
377
        data = response_handler.read_body_bytes()
336
 
        # Cache the results, but only until they have been fulfilled
337
 
        data_map = {}
338
378
        data_offset = 0
339
379
        for c_offset in coalesced:
340
380
            if len(data) < c_offset.length:
353
393
                #       not have a real string.
354
394
                if key == cur_offset_and_size:
355
395
                    yield cur_offset_and_size[0], this_data
356
 
                    cur_offset_and_size = offset_stack.next()
 
396
                    cur_offset_and_size = next_offset[0] = offset_stack.next()
357
397
                else:
358
398
                    data_map[key] = this_data
359
399
            data_offset += c_offset.length
362
402
            while cur_offset_and_size in data_map:
363
403
                this_data = data_map.pop(cur_offset_and_size)
364
404
                yield cur_offset_and_size[0], this_data
365
 
                cur_offset_and_size = offset_stack.next()
 
405
                cur_offset_and_size = next_offset[0] = offset_stack.next()
366
406
 
367
407
    def rename(self, rel_from, rel_to):
368
408
        self._call('rename',
381
421
        if resp[0] != 'ok':
382
422
            raise errors.UnexpectedSmartServerResponse(resp)
383
423
        
384
 
    def _translate_error(self, err, orig_path=None):
385
 
        remote._translate_error(err, path=orig_path)
 
424
    def _translate_error(self, err, relpath=None):
 
425
        remote._translate_error(err, path=relpath)
386
426
 
387
427
    def disconnect(self):
388
428
        self.get_smart_medium().disconnect()