125
125
self.get(key).insert(0, registry._ObjectGetter(obj))
127
127
def register_lazy_transport_provider(self, key, module_name, member_name):
128
self.get(key).insert(0,
128
self.get(key).insert(0,
129
129
registry._LazyObjectGetter(module_name, member_name))
131
def register_transport(self, key, help=None, info=None):
132
self.register(key, [], help, info)
131
def register_transport(self, key, help=None, default_port=None):
132
self.register(key, [], help, default_port)
134
134
def set_default_transport(self, key=None):
135
135
"""Return either 'key' or the default key if key is None"""
136
136
self._default_key = key
139
transport_list_registry = TransportListRegistry( )
142
def register_transport_proto(prefix, help=None, info=None):
143
transport_list_registry.register_transport(prefix, help, info)
138
def get_default_port(self, scheme):
139
"""Return the registered default port for this protocol scheme."""
141
return self.get_info(scheme + '://')
146
transport_list_registry = TransportListRegistry()
149
def register_transport_proto(prefix, help=None, info=None, default_port=None):
150
transport_list_registry.register_transport(prefix, help, default_port)
146
153
def register_lazy_transport(prefix, module, classname):
636
643
raise errors.NoSmartMedium(self)
638
def readv(self, relpath, offsets):
639
"""Get parts of the file at the given relative path.
641
:offsets: A list of (offset, size) tuples.
645
def readv(self, relpath, offsets, adjust_for_latency=False,
647
"""Get parts of the file at the given relative path.
649
:param relpath: The path to read data from.
650
:param offsets: A list of (offset, size) tuples.
651
:param adjust_for_latency: Adjust the requested offsets to accomdate
652
transport latency. This may re-order the offsets, expand them to
653
grab adjacent data when there is likely a high cost to requesting
654
data relative to delivering it.
655
:param upper_limit: When adjust_for_latency is True setting upper_limit
656
allows the caller to tell the transport about the length of the
657
file, so that requests are not issued for ranges beyond the end of
658
the file. This matters because some servers and/or transports error
659
in such a case rather than just satisfying the available ranges.
660
upper_limit should always be provided when adjust_for_latency is
661
True, and should be the size of the file in bytes.
662
:return: A list or generator of (offset, data) tuples
664
if adjust_for_latency:
665
offsets = sorted(offsets)
666
# short circuit empty requests
667
if len(offsets) == 0:
669
# Quick thunk to stop this function becoming a generator
670
# itself, rather we return a generator that has nothing to
674
return empty_yielder()
675
# expand by page size at either end
676
maximum_expansion = self.recommended_page_size()
678
for offset, length in offsets:
679
expansion = maximum_expansion - length
681
# we're asking for more than the minimum read anyway.
683
reduction = expansion / 2
684
new_offset = offset - reduction
685
new_length = length + expansion
687
# don't ask for anything < 0
689
if (upper_limit is not None and
690
new_offset + new_length > upper_limit):
691
new_length = upper_limit - new_offset
692
new_offsets.append((new_offset, new_length))
693
# combine the expanded offsets
695
current_offset, current_length = new_offsets[0]
696
current_finish = current_length + current_offset
697
for offset, length in new_offsets[1:]:
698
if offset > current_finish:
699
offsets.append((current_offset, current_length))
700
current_offset = offset
701
current_length = length
703
finish = offset + length
704
if finish > current_finish:
705
current_finish = finish
706
offsets.append((current_offset, current_length))
707
return self._readv(relpath, offsets)
709
def _readv(self, relpath, offsets):
710
"""Get parts of the file at the given relative path.
712
:param relpath: The path to read.
713
:param offsets: A list of (offset, size) tuples.
642
714
:return: A list or generator of (offset, data) tuples
1286
1362
# have one so that it doesn't get accidentally
1288
1364
netloc = '%s@%s' % (urllib.quote(user), netloc)
1289
if port is not None:
1365
if (port is not None and
1366
port != transport_list_registry.get_default_port(scheme)):
1367
# Include the port in the netloc (unless it's the same as the
1368
# default, in which case we omit it as it is redundant).
1290
1369
netloc = '%s:%d' % (netloc, port)
1291
1370
path = urllib.quote(path)
1292
1371
return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1595
1674
raise NotImplementedError
1598
class TransportLogger(object):
1599
"""Adapt a transport to get clear logging data on api calls.
1601
Feel free to extend to log whatever calls are of interest.
1604
def __init__(self, adapted):
1605
self._adapted = adapted
1608
def get(self, name):
1609
self._calls.append((name,))
1610
return self._adapted.get(name)
1612
def __getattr__(self, name):
1613
"""Thunk all undefined access through to self._adapted."""
1614
# raise AttributeError, name
1615
return getattr(self._adapted, name)
1617
def readv(self, name, offsets):
1618
self._calls.append((name, offsets))
1619
return self._adapted.readv(name, offsets)
1622
1677
# None is the default transport, for things with no url scheme
1623
1678
register_transport_proto('file://',
1624
1679
help="Access using the standard filesystem (default)")
1626
1681
transport_list_registry.set_default_transport("file://")
1628
1683
register_transport_proto('sftp://',
1629
help="Access using SFTP (most SSH servers provide SFTP).")
1684
help="Access using SFTP (most SSH servers provide SFTP).",
1630
1686
register_lazy_transport('sftp://', 'bzrlib.transport.sftp', 'SFTPTransport')
1631
1687
# Decorated http transport
1632
1688
register_transport_proto('http+urllib://',
1633
1689
# help="Read-only access of branches exported on the web."
1635
1691
register_lazy_transport('http+urllib://', 'bzrlib.transport.http._urllib',
1636
1692
'HttpTransport_urllib')
1637
1693
register_transport_proto('https+urllib://',
1638
1694
# help="Read-only access of branches exported on the web using SSL."
1640
1696
register_lazy_transport('https+urllib://', 'bzrlib.transport.http._urllib',
1641
1697
'HttpTransport_urllib')
1642
1698
register_transport_proto('http+pycurl://',
1643
1699
# help="Read-only access of branches exported on the web."
1645
1701
register_lazy_transport('http+pycurl://', 'bzrlib.transport.http._pycurl',
1646
1702
'PyCurlTransport')
1647
1703
register_transport_proto('https+pycurl://',
1648
1704
# help="Read-only access of branches exported on the web using SSL."
1650
1706
register_lazy_transport('https+pycurl://', 'bzrlib.transport.http._pycurl',
1651
1707
'PyCurlTransport')
1652
1708
# Default http transports (last declared wins (if it can be imported))
1653
1709
register_transport_proto('http://',
1654
help="Read-only access of branches exported on the web.")
1710
help="Read-only access of branches exported on the web.",
1655
1712
register_transport_proto('https://',
1656
help="Read-only access of branches exported on the web using SSL.")
1713
help="Read-only access of branches exported on the web using SSL.",
1657
1715
register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
1658
1716
'HttpTransport_urllib')
1659
1717
register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
1662
1720
register_lazy_transport('https://', 'bzrlib.transport.http._pycurl', 'PyCurlTransport')
1664
1722
register_transport_proto('ftp://',
1665
help="Access using passive FTP.")
1723
help="Access using passive FTP.",
1666
1725
register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1667
1726
register_transport_proto('aftp://',
1668
help="Access using active FTP.")
1727
help="Access using active FTP.",
1669
1729
register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
1671
1731
register_transport_proto('memory://')
1672
1732
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
1734
# chroots cannot be implicitly accessed, they must be explicitly created:
1673
1735
register_transport_proto('chroot+')
1675
1737
register_transport_proto('readonly+',
1680
1742
register_transport_proto('fakenfs+')
1681
1743
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1745
register_transport_proto('trace+')
1746
register_lazy_transport('trace+', 'bzrlib.transport.trace', 'TransportTraceDecorator')
1683
1748
register_transport_proto('unlistable+')
1684
1749
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable', 'UnlistableTransportDecorator')
1692
1757
'bzrlib.transport.fakevfat',
1693
1758
'FakeVFATTransportDecorator')
1694
1759
register_transport_proto('bzr://',
1695
help="Fast access using the Bazaar smart server.")
1760
help="Fast access using the Bazaar smart server.",
1697
1763
register_lazy_transport('bzr://',
1698
1764
'bzrlib.transport.remote',
1699
1765
'RemoteTCPTransport')
1700
1766
register_transport_proto('bzr+http://',
1701
1767
# help="Fast access using the Bazaar smart server over HTTP."
1769
register_lazy_transport('bzr+http://',
1770
'bzrlib.transport.remote',
1771
'RemoteHTTPTransport')
1772
register_transport_proto('bzr+https://',
1773
# help="Fast access using the Bazaar smart server over HTTPS."
1703
register_lazy_transport('bzr+http://',
1775
register_lazy_transport('bzr+https://',
1704
1776
'bzrlib.transport.remote',
1705
1777
'RemoteHTTPTransport')
1706
1778
register_transport_proto('bzr+ssh://',
1707
help="Fast access using the Bazaar smart server over SSH.")
1779
help="Fast access using the Bazaar smart server over SSH.",
1708
1781
register_lazy_transport('bzr+ssh://',
1709
1782
'bzrlib.transport.remote',
1710
1783
'RemoteSSHTransport')