43
43
self.st_mode = mode
46
class RemoteTransport(transport.ConnectedTransport):
46
class RemoteTransport(transport.ConnectedTransport, medium.SmartClientMedium):
47
47
"""Connection to a smart server.
49
49
The connection holds references to the medium that can be used to send
312
312
offsets = list(offsets)
314
314
sorted_offsets = sorted(offsets)
315
# turn the list of offsets into a stack
316
offset_stack = iter(offsets)
317
cur_offset_and_size = offset_stack.next()
318
315
coalesced = list(self._coalesce_offsets(sorted_offsets,
319
316
limit=self._max_readv_combine,
320
317
fudge_factor=self._bytes_to_read_before_seek))
332
329
response_handler.cancel_read_body()
333
330
raise errors.UnexpectedSmartServerResponse(resp)
332
return self._handle_response(offsets, coalesced, response_handler)
334
def _handle_response(self, offsets, coalesced, response_handler):
335
# turn the list of offsets into a stack
336
offset_stack = iter(offsets)
337
cur_offset_and_size = offset_stack.next()
335
338
# FIXME: this should know how many bytes are needed, for clarity.
336
339
data = response_handler.read_body_bytes()
337
340
# Cache the results, but only until they have been fulfilled
339
343
for c_offset in coalesced:
340
344
if len(data) < c_offset.length:
341
345
raise errors.ShortReadvError(relpath, c_offset.start,
342
346
c_offset.length, actual=len(data))
343
347
for suboffset, subsize in c_offset.ranges:
344
348
key = (c_offset.start+suboffset, subsize)
345
data_map[key] = data[suboffset:suboffset+subsize]
346
data = data[c_offset.length:]
349
this_data = data[data_offset+suboffset:
350
data_offset+suboffset+subsize]
351
# Special case when the data is in-order, rather than packing
352
# into a map and then back out again. Benchmarking shows that
353
# this has 100% hit rate, but leave in the data_map work just
355
# TODO: Could we get away with using buffer() to avoid the
356
# memory copy? Callers would need to realize they may
357
# not have a real string.
358
if key == cur_offset_and_size:
359
yield cur_offset_and_size[0], this_data
360
cur_offset_and_size = offset_stack.next()
362
data_map[key] = this_data
363
data_offset += c_offset.length
348
365
# Now that we've read some data, see if we can yield anything back
349
366
while cur_offset_and_size in data_map: