~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

  • Committer: Jelmer Vernooij
  • Date: 2009-02-23 20:55:58 UTC
  • mfrom: (4034 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4053.
  • Revision ID: jelmer@samba.org-20090223205558-1cx2k4w1zgs8r5qa
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
87
87
 
88
88
def _get_line(read_bytes_func):
89
89
    """Read bytes using read_bytes_func until a newline byte.
90
 
    
 
90
 
91
91
    This isn't particularly efficient, so should only be used when the
92
92
    expected size of the line is quite short.
93
 
    
 
93
 
94
94
    :returns: a tuple of two strs: (line, excess)
95
95
    """
96
96
    newline_pos = -1
112
112
 
113
113
    def __init__(self):
114
114
        self._push_back_buffer = None
115
 
        
 
115
 
116
116
    def _push_back(self, bytes):
117
117
        """Return unused bytes to the medium, because they belong to the next
118
118
        request(s).
152
152
 
153
153
    def _get_line(self):
154
154
        """Read bytes from this request's response until a newline byte.
155
 
        
 
155
 
156
156
        This isn't particularly efficient, so should only be used when the
157
157
        expected size of the line is quite short.
158
158
 
161
161
        line, excess = _get_line(self.read_bytes)
162
162
        self._push_back(excess)
163
163
        return line
164
 
 
 
164
 
165
165
 
166
166
class SmartServerStreamMedium(SmartMedium):
167
167
    """Handles smart commands coming over a stream.
172
172
    One instance is created for each connected client; it can serve multiple
173
173
    requests in the lifetime of the connection.
174
174
 
175
 
    The server passes requests through to an underlying backing transport, 
 
175
    The server passes requests through to an underlying backing transport,
176
176
    which will typically be a LocalTransport looking at the server's filesystem.
177
177
 
178
178
    :ivar _push_back_buffer: a str of bytes that have been read from the stream
223
223
 
224
224
    def _serve_one_request(self, protocol):
225
225
        """Read one request from input, process, send back a response.
226
 
        
 
226
 
227
227
        :param protocol: a SmartServerRequestProtocol.
228
228
        """
229
229
        try:
268
268
                self.finished = True
269
269
                return
270
270
            protocol.accept_bytes(bytes)
271
 
        
 
271
 
272
272
        self._push_back(protocol.unused_data)
273
273
 
274
274
    def _read_bytes(self, desired_count):
350
350
    request.finished_reading()
351
351
 
352
352
    It is up to the individual SmartClientMedium whether multiple concurrent
353
 
    requests can exist. See SmartClientMedium.get_request to obtain instances 
354
 
    of SmartClientMediumRequest, and the concrete Medium you are using for 
 
353
    requests can exist. See SmartClientMedium.get_request to obtain instances
 
354
    of SmartClientMediumRequest, and the concrete Medium you are using for
355
355
    details on concurrency and pipelining.
356
356
    """
357
357
 
403
403
    def _finished_reading(self):
404
404
        """Helper for finished_reading.
405
405
 
406
 
        finished_reading checks the state of the request to determine if 
 
406
        finished_reading checks the state of the request to determine if
407
407
        finished_reading is allowed, and if it is hands off to _finished_reading
408
408
        to perform the action.
409
409
        """
423
423
    def _finished_writing(self):
424
424
        """Helper for finished_writing.
425
425
 
426
 
        finished_writing checks the state of the request to determine if 
 
426
        finished_writing checks the state of the request to determine if
427
427
        finished_writing is allowed, and if it is hands off to _finished_writing
428
428
        to perform the action.
429
429
        """
449
449
        read_bytes checks the state of the request to determing if bytes
450
450
        should be read. After that it hands off to _read_bytes to do the
451
451
        actual read.
452
 
        
 
452
 
453
453
        By default this forwards to self._medium.read_bytes because we are
454
454
        operating on the medium's stream.
455
455
        """
466
466
 
467
467
    def _read_line(self):
468
468
        """Helper for SmartClientMediumRequest.read_line.
469
 
        
 
469
 
470
470
        By default this forwards to self._medium._get_line because we are
471
471
        operating on the medium's stream.
472
472
        """
516
516
        value[0] = 0
517
517
        if count != 0:
518
518
            trace.note('HPSS calls: %d %s', count, medium_repr)
519
 
        
 
519
 
520
520
    def flush_all(self):
521
521
        for ref in list(self.counts.keys()):
522
522
            self.done(ref)
523
523
 
524
524
_debug_counter = None
525
 
  
526
 
  
 
525
 
 
526
 
527
527
class SmartClientMedium(SmartMedium):
528
528
    """Smart client is a medium for sending smart protocol requests over."""
529
529
 
574
574
        """
575
575
        if (self._remote_version_is_before is not None and
576
576
            version_tuple > self._remote_version_is_before):
 
577
            # We have been told that the remote side is older than some version
 
578
            # which is newer than a previously supplied older-than version.
 
579
            # This indicates that some smart verb call is not guarded
 
580
            # appropriately (it should simply not have been tried).
577
581
            raise AssertionError(
578
582
                "_remember_remote_is_before(%r) called, but "
579
583
                "_remember_remote_is_before(%r) was called previously."
617
621
 
618
622
    def disconnect(self):
619
623
        """If this medium maintains a persistent connection, close it.
620
 
        
 
624
 
621
625
        The default implementation does nothing.
622
626
        """
623
 
        
 
627
 
624
628
    def remote_path_from_transport(self, transport):
625
629
        """Convert transport into a path suitable for using in a request.
626
 
        
 
630
 
627
631
        Note that the resulting remote path doesn't encode the host name or
628
632
        anything but path, so it is only safe to use it in requests sent over
629
633
        the medium from the matching transport.
657
661
 
658
662
    def _flush(self):
659
663
        """Flush the output stream.
660
 
        
 
664
 
661
665
        This method is used by the SmartClientStreamMediumRequest to ensure that
662
666
        all data for a request is sent, to avoid long timeouts or deadlocks.
663
667
        """
674
678
 
675
679
class SmartSimplePipesClientMedium(SmartClientStreamMedium):
676
680
    """A client medium using simple pipes.
677
 
    
 
681
 
678
682
    This client does not manage the pipes: it assumes they will always be open.
679
683
    """
680
684
 
698
702
 
699
703
class SmartSSHClientMedium(SmartClientStreamMedium):
700
704
    """A client medium using SSH."""
701
 
    
 
705
 
702
706
    def __init__(self, host, port=None, username=None, password=None,
703
707
            base=None, vendor=None, bzr_remote_path=None):
704
708
        """Creates a client that will connect on the first use.
705
 
        
 
709
 
706
710
        :param vendor: An optional override for the ssh vendor to use. See
707
711
            bzrlib.transport.ssh for details on ssh vendors.
708
712
        """
772
776
 
773
777
class SmartTCPClientMedium(SmartClientStreamMedium):
774
778
    """A client medium using TCP."""
775
 
    
 
779
 
776
780
    def __init__(self, host, port, base):
777
781
        """Creates a client that will connect on the first use."""
778
782
        SmartClientStreamMedium.__init__(self, base)
803
807
        else:
804
808
            port = int(self._port)
805
809
        try:
806
 
            sockaddrs = socket.getaddrinfo(self._host, port, socket.AF_UNSPEC, 
 
810
            sockaddrs = socket.getaddrinfo(self._host, port, socket.AF_UNSPEC,
807
811
                socket.SOCK_STREAM, 0, 0)
808
812
        except socket.gaierror, (err_num, err_msg):
809
813
            raise errors.ConnectionError("failed to lookup %s:%d: %s" %
813
817
        for (family, socktype, proto, canonname, sockaddr) in sockaddrs:
814
818
            try:
815
819
                self._socket = socket.socket(family, socktype, proto)
816
 
                self._socket.setsockopt(socket.IPPROTO_TCP, 
 
820
                self._socket.setsockopt(socket.IPPROTO_TCP,
817
821
                                        socket.TCP_NODELAY, 1)
818
822
                self._socket.connect(sockaddr)
819
823
            except socket.error, err:
835
839
 
836
840
    def _flush(self):
837
841
        """See SmartClientStreamMedium._flush().
838
 
        
839
 
        For TCP we do no flushing. We may want to turn off TCP_NODELAY and 
 
842
 
 
843
        For TCP we do no flushing. We may want to turn off TCP_NODELAY and
840
844
        add a means to do a flush, but that can be done in the future.
841
845
        """
842
846
 
872
876
 
873
877
    def _accept_bytes(self, bytes):
874
878
        """See SmartClientMediumRequest._accept_bytes.
875
 
        
 
879
 
876
880
        This forwards to self._medium._accept_bytes because we are operating
877
881
        on the mediums stream.
878
882
        """
881
885
    def _finished_reading(self):
882
886
        """See SmartClientMediumRequest._finished_reading.
883
887
 
884
 
        This clears the _current_request on self._medium to allow a new 
 
888
        This clears the _current_request on self._medium to allow a new
885
889
        request to be created.
886
890
        """
887
891
        if self._medium._current_request is not self:
888
892
            raise AssertionError()
889
893
        self._medium._current_request = None
890
 
        
 
894
 
891
895
    def _finished_writing(self):
892
896
        """See SmartClientMediumRequest._finished_writing.
893
897