209
210
as a single parameter.
211
212
total = self._get_total(multi)
213
215
for entry in multi:
214
216
self._update_pb(pb, msg, count, total)
218
result.append(func(*entry))
220
result.append(func(entry))
222
224
def abspath(self, relpath):
223
225
"""Return the full url to the given relative path.
247
249
"""Does the file relpath exist?
249
251
Note that some transports MAY allow querying on directories, but this
250
is not part of the protocol.
252
is not part of the protocol. In other words, the results of
253
t.has("a_directory_name") are undefined."
252
255
raise NotImplementedError(self.has)
288
291
raise NotImplementedError(self.get)
293
def readv(self, relpath, offsets):
294
"""Get parts of the file at the given relative path.
296
:offsets: A list of (offset, size) tuples.
297
:return: A list or generator of (offset, data) tuples
299
def do_combined_read(combined_offsets):
301
for offset, size in combined_offsets:
303
mutter('readv coalesced %d reads.', len(combined_offsets))
304
offset = combined_offsets[0][0]
306
data = fp.read(total_size)
308
for offset, size in combined_offsets:
309
yield offset, data[pos:pos + size]
314
fp = self.get(relpath)
315
pending_offsets = deque(offsets)
316
combined_offsets = []
317
while len(pending_offsets):
318
offset, size = pending_offsets.popleft()
319
if not combined_offsets:
320
combined_offsets = [[offset, size]]
322
if (len (combined_offsets) < 50 and
323
combined_offsets[-1][0] + combined_offsets[-1][1] == offset):
325
combined_offsets.append([offset, size])
327
# incompatible, or over the threshold issue a read and yield
328
pending_offsets.appendleft((offset, size))
329
for result in do_combined_read(combined_offsets):
331
combined_offsets = []
332
# whatever is left is a single coalesced request
333
if len(combined_offsets):
334
for result in do_combined_read(combined_offsets):
290
337
def get_multi(self, relpaths, pb=None):
291
338
"""Get a list of file-like objects, one for each entry in relpaths.
325
372
def put(path, f):
326
373
self.put(path, f, mode=mode)
327
return self._iterate_over(files, put, pb, 'put', expand=True)
374
return len(self._iterate_over(files, put, pb, 'put', expand=True))
329
376
def mkdir(self, relpath, mode=None):
330
377
"""Create a directory at the given path."""
334
381
"""Create a group of directories"""
336
383
self.mkdir(path, mode=mode)
337
return self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False)
384
return len(self._iterate_over(relpaths, mkdir, pb, 'mkdir', expand=False))
339
386
def append(self, relpath, f):
340
387
"""Append the text in the file-like or string object to
341
388
the supplied location.
390
returns the length of f before the content was written to it.
343
392
raise NotImplementedError(self.append)
380
429
def copy_entry(path):
381
430
other.put(path, self.get(path), mode=mode)
383
return self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False)
432
return len(self._iterate_over(relpaths, copy_entry, pb, 'copy_to', expand=False))
385
434
def copy_tree(self, from_relpath, to_relpath):
386
435
"""Copy a subtree from one relpath to another.
675
724
# from running this test
729
class TransportLogger(object):
730
"""Adapt a transport to get clear logging data on api calls.
732
Feel free to extend to log whatever calls are of interest.
735
def __init__(self, adapted):
736
self._adapted = adapted
740
self._calls.append((name,))
741
return self._adapted.get(name)
743
def __getattr__(self, name):
744
"""Thunk all undefined access through to self._adapted."""
745
# raise AttributeError, name
746
return getattr(self._adapted, name)
748
def readv(self, name, offsets):
749
self._calls.append((name, offsets))
750
return self._adapted.readv(name, offsets)
680
753
# None is the default transport, for things with no url scheme
682
755
register_lazy_transport('file://', 'bzrlib.transport.local', 'LocalTransport')
683
756
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
684
757
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
758
'HttpTransport_urllib')
686
759
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
688
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
690
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
692
register_lazy_transport('http://', 'bzrlib.transport.http._urllib', 'HttpTransport')
693
register_lazy_transport('https://', 'bzrlib.transport.http._urllib', 'HttpTransport')
760
'HttpTransport_urllib')
761
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
763
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
765
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
766
'HttpTransport_urllib')
767
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
768
'HttpTransport_urllib')
694
769
register_lazy_transport('http://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
695
770
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
696
771
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')