250
251
:offsets: A list of (offset, size) tuples.
251
252
:return: A list or generator of (offset, data) tuples
254
def do_combined_read(combined_offsets):
256
for offset, size in combined_offsets:
258
mutter('readv coalesced %d reads.', len(combined_offsets))
259
offset = combined_offsets[0][0]
261
data = fp.read(total_size)
263
for offset, size in combined_offsets:
264
yield offset, data[pos:pos + size]
253
267
if not len(offsets):
255
269
fp = self.get(relpath)
257
new_offsets = [list(offsets[0])]
258
for offset, size in offsets[1:]:
259
if offset == new_offsets[-1][0] + new_offsets[-1][1]:
260
new_offsets[-1][1] += size
270
pending_offsets = deque(offsets)
271
combined_offsets = []
272
while len(pending_offsets):
273
offset, size = pending_offsets.popleft()
274
if not combined_offsets:
275
combined_offsets = [[offset, size]]
262
new_offsets.append([offset, size])
263
mutter('readv coalesced %d reads to %d', len(offsets), len(new_offsets))
264
for offset, size in new_offsets:
266
yield offset, fp.read(size)
277
if combined_offsets[-1][0] + combined_offsets[-1][1] == offset:
279
combined_offsets.append([offset, size])
281
# incompatible, issue a read and yield
282
pending_offsets.appendleft((offset, size))
283
for result in do_combined_read(combined_offsets):
285
combined_offsets = []
286
# whatever is left is a single coalesced request
287
if len(combined_offsets):
288
for result in do_combined_read(combined_offsets):
268
291
def get_multi(self, relpaths, pb=None):
269
292
"""Get a list of file-like objects, one for each entry in relpaths.