~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/__init__.py

  • Committer: Robert Collins
  • Date: 2007-10-02 05:33:39 UTC
  • mto: This revision was merged to the branch mainline in revision 2885.
  • Revision ID: robertc@robertcollins.net-20071002053339-vnyjf4jrxv0jeekf
* Move transport logging into a new transport class
  TransportTraceDecorator (trace+ to get it from a url).
* Give Registry a useful __repr__.
* Fix a bug introduced by the change to use a Registry for transport where
  the transport loading tests left global state behind due to the
  _get_protocol_handlers method returning a reference, not a value object.
* Add an upper_limit parameter to readv, because when asking for byte
  ranges within the latency-adjustment window near the end of the file
  causes errors that are tricky to manage.
* A few minor drive-by formatting fixes.
* The TransportDecorator constructor now accepts a _from_transport
  parameter for decorators that want to share state (used by the trace
  decorator)

Show diffs side-by-side

added added

removed removed

Lines of Context:
99
99
                modules.add(factory._module_name)
100
100
            else:
101
101
                modules.add(factory._obj.__module__)
102
 
    # Add chroot directly, because there is not handler registered for it.
 
102
    # Add chroot directly, because there is no handler registered for it.
103
103
    modules.add('bzrlib.transport.chroot')
104
104
    result = list(modules)
105
105
    result.sort()
125
125
        self.get(key).insert(0, registry._ObjectGetter(obj))
126
126
 
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))
130
130
 
131
131
    def register_transport(self, key, help=None, info=None):
136
136
        self._default_key = key
137
137
 
138
138
 
139
 
transport_list_registry = TransportListRegistry( )
 
139
transport_list_registry = TransportListRegistry()
140
140
 
141
141
 
142
142
def register_transport_proto(prefix, help=None, info=None):
635
635
        """
636
636
        raise errors.NoSmartMedium(self)
637
637
 
638
 
    def readv(self, relpath, offsets, adjust_for_latency=False):
 
638
    def readv(self, relpath, offsets, adjust_for_latency=False,
 
639
        upper_limit=None):
639
640
        """Get parts of the file at the given relative path.
640
641
 
641
642
        :param relpath: The path to read data from.
644
645
            transport latency. This may re-order the offsets, expand them to
645
646
            grab adjacent data when there is likely a high cost to requesting
646
647
            data relative to delivering it.
 
648
        :param upper_limit: When adjust_for_latency is True setting upper_limit
 
649
            allows the caller to tell the transport about the length of the
 
650
            file, so that requests are not issued for ranges beyond the end of
 
651
            the file. This matters because some servers and/or transports error
 
652
            in such a case rather than just satisfying the available ranges.
 
653
            upper_limit should always be provided when adjust_for_latency is
 
654
            True, and should be the size of the file in bytes.
647
655
        :return: A list or generator of (offset, data) tuples
648
656
        """
649
657
        if adjust_for_latency:
658
666
                        yield None
659
667
                return empty_yielder()
660
668
            # expand by page size at either end
661
 
            expansion = self.recommended_page_size() / 2
 
669
            expansion = self.recommended_page_size()
 
670
            reduction = expansion / 2
662
671
            new_offsets = []
663
672
            for offset, length in offsets:
664
 
                new_offset = offset - expansion
 
673
                new_offset = offset - reduction
665
674
                new_length = length + expansion
666
675
                if new_offset < 0:
667
676
                    # don't ask for anything < 0
668
677
                    new_length -= new_offset
669
678
                    new_offset = 0
 
679
                if (upper_limit is not None and
 
680
                    new_offset + new_length > upper_limit):
 
681
                    new_length = upper_limit - new_offset
670
682
                new_offsets.append((new_offset, new_length))
671
683
            # combine the expanded offsets
672
684
            offsets = []
687
699
    def _readv(self, relpath, offsets):
688
700
        """Get parts of the file at the given relative path.
689
701
 
690
 
        :offsets: A list of (offset, size) tuples.
 
702
        :param relpath: The path to read.
 
703
        :param offsets: A list of (offset, size) tuples.
691
704
        :return: A list or generator of (offset, data) tuples
692
705
        """
693
706
        if not offsets:
1644
1657
        raise NotImplementedError
1645
1658
 
1646
1659
 
1647
 
class TransportLogger(object):
1648
 
    """Adapt a transport to get clear logging data on api calls.
1649
 
    
1650
 
    Feel free to extend to log whatever calls are of interest.
1651
 
    """
1652
 
 
1653
 
    def __init__(self, adapted):
1654
 
        self._adapted = adapted
1655
 
        self._calls = []
1656
 
 
1657
 
    def get(self, name):
1658
 
        self._calls.append((name,))
1659
 
        return self._adapted.get(name)
1660
 
 
1661
 
    def __getattr__(self, name):
1662
 
        """Thunk all undefined access through to self._adapted."""
1663
 
        # raise AttributeError, name 
1664
 
        return getattr(self._adapted, name)
1665
 
 
1666
 
    def readv(self, name, offsets):
1667
 
        self._calls.append((name, offsets))
1668
 
        return self._adapted.readv(name, offsets)
1669
 
 
1670
 
 
1671
1660
# None is the default transport, for things with no url scheme
1672
1661
register_transport_proto('file://',
1673
1662
            help="Access using the standard filesystem (default)")
1719
1708
 
1720
1709
register_transport_proto('memory://')
1721
1710
register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
 
1711
 
 
1712
# chroots cannot be implicitly accessed, they must be explicitly created:
1722
1713
register_transport_proto('chroot+')
1723
1714
 
1724
1715
register_transport_proto('readonly+',
1729
1720
register_transport_proto('fakenfs+')
1730
1721
register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
1731
1722
 
 
1723
register_transport_proto('trace+')
 
1724
register_lazy_transport('trace+', 'bzrlib.transport.trace', 'TransportTraceDecorator')
 
1725
 
1732
1726
register_transport_proto('unlistable+')
1733
1727
register_lazy_transport('unlistable+', 'bzrlib.transport.unlistable', 'UnlistableTransportDecorator')
1734
1728