~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

  • Committer: Robert Collins
  • Date: 2010-04-08 04:34:03 UTC
  • mfrom: (5138 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5139.
  • Revision ID: robertc@robertcollins.net-20100408043403-56z0d07vdqrx7f3t
Update bugfix for 528114 to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
bzrlib/transport/smart/__init__.py.
25
25
"""
26
26
 
27
 
import errno
28
27
import os
29
 
import socket
30
28
import sys
31
29
import urllib
32
30
 
33
31
from bzrlib.lazy_import import lazy_import
34
32
lazy_import(globals(), """
35
33
import atexit
 
34
import socket
36
35
import thread
37
36
import weakref
38
37
 
47
46
from bzrlib.smart import client, protocol, request, vfs
48
47
from bzrlib.transport import ssh
49
48
""")
50
 
#usually already imported, and getting IllegalScoperReplacer on it here.
51
49
from bzrlib import osutils
52
50
 
53
 
# We must not read any more than 64k at a time so we don't risk "no buffer
54
 
# space available" errors on some platforms.  Windows in particular is likely
55
 
# to give error 10053 or 10055 if we read more than 64k from a socket.
56
 
_MAX_READ_SIZE = 64 * 1024
57
 
 
 
51
# Throughout this module buffer size parameters are either limited to be at
 
52
# most _MAX_READ_SIZE, or are ignored and _MAX_READ_SIZE is used instead.
 
53
# For this module's purposes, MAX_SOCKET_CHUNK is a reasonable size for reads
 
54
# from non-sockets as well.
 
55
_MAX_READ_SIZE = osutils.MAX_SOCKET_CHUNK
58
56
 
59
57
def _get_protocol_factory_for_bytes(bytes):
60
58
    """Determine the right protocol factory for 'bytes'.
276
274
    def _serve_one_request_unguarded(self, protocol):
277
275
        while protocol.next_read_size():
278
276
            # We can safely try to read large chunks.  If there is less data
279
 
            # than _MAX_READ_SIZE ready, the socket wil just return a short
280
 
            # read immediately rather than block.
281
 
            bytes = self.read_bytes(_MAX_READ_SIZE)
 
277
            # than MAX_SOCKET_CHUNK ready, the socket will just return a
 
278
            # short read immediately rather than block.
 
279
            bytes = self.read_bytes(osutils.MAX_SOCKET_CHUNK)
282
280
            if bytes == '':
283
281
                self.finished = True
284
282
                return
287
285
        self._push_back(protocol.unused_data)
288
286
 
289
287
    def _read_bytes(self, desired_count):
290
 
        return _read_bytes_from_socket(
291
 
            self.socket.recv, desired_count, self._report_activity)
 
288
        return osutils.read_bytes_from_socket(
 
289
            self.socket, self._report_activity)
292
290
 
293
291
    def terminate_due_to_error(self):
294
292
        # TODO: This should log to a server log file, but no such thing
295
293
        # exists yet.  Andrew Bennetts 2006-09-29.
296
 
        osutils.until_no_eintr(self.socket.close)
 
294
        self.socket.close()
297
295
        self.finished = True
298
296
 
299
297
    def _write_out(self, bytes):
334
332
            bytes_to_read = protocol.next_read_size()
335
333
            if bytes_to_read == 0:
336
334
                # Finished serving this request.
337
 
                osutils.until_no_eintr(self._out.flush)
 
335
                self._out.flush()
338
336
                return
339
337
            bytes = self.read_bytes(bytes_to_read)
340
338
            if bytes == '':
341
339
                # Connection has been closed.
342
340
                self.finished = True
343
 
                osutils.until_no_eintr(self._out.flush)
 
341
                self._out.flush()
344
342
                return
345
343
            protocol.accept_bytes(bytes)
346
344
 
347
345
    def _read_bytes(self, desired_count):
348
 
        return osutils.until_no_eintr(self._in.read, desired_count)
 
346
        return self._in.read(desired_count)
349
347
 
350
348
    def terminate_due_to_error(self):
351
349
        # TODO: This should log to a server log file, but no such thing
352
350
        # exists yet.  Andrew Bennetts 2006-09-29.
353
 
        osutils.until_no_eintr(self._out.close)
 
351
        self._out.close()
354
352
        self.finished = True
355
353
 
356
354
    def _write_out(self, bytes):
357
 
        osutils.until_no_eintr(self._out.write, bytes)
 
355
        self._out.write(bytes)
358
356
 
359
357
 
360
358
class SmartClientMediumRequest(object):
711
709
    """A client medium using simple pipes.
712
710
 
713
711
    This client does not manage the pipes: it assumes they will always be open.
 
712
 
 
713
    Note that if readable_pipe.read might raise IOError or OSError with errno
 
714
    of EINTR, it must be safe to retry the read.  Plain CPython fileobjects
 
715
    (such as used for sys.stdin) are safe.
714
716
    """
715
717
 
716
718
    def __init__(self, readable_pipe, writeable_pipe, base):
720
722
 
721
723
    def _accept_bytes(self, bytes):
722
724
        """See SmartClientStreamMedium.accept_bytes."""
723
 
        osutils.until_no_eintr(self._writeable_pipe.write, bytes)
 
725
        self._writeable_pipe.write(bytes)
724
726
        self._report_activity(len(bytes), 'write')
725
727
 
726
728
    def _flush(self):
727
729
        """See SmartClientStreamMedium._flush()."""
728
 
        osutils.until_no_eintr(self._writeable_pipe.flush)
 
730
        self._writeable_pipe.flush()
729
731
 
730
732
    def _read_bytes(self, count):
731
733
        """See SmartClientStreamMedium._read_bytes."""
777
779
    def _accept_bytes(self, bytes):
778
780
        """See SmartClientStreamMedium.accept_bytes."""
779
781
        self._ensure_connection()
780
 
        osutils.until_no_eintr(self._write_to.write, bytes)
 
782
        self._write_to.write(bytes)
781
783
        self._report_activity(len(bytes), 'write')
782
784
 
783
785
    def disconnect(self):
784
786
        """See SmartClientMedium.disconnect()."""
785
787
        if not self._connected:
786
788
            return
787
 
        osutils.until_no_eintr(self._read_from.close)
788
 
        osutils.until_no_eintr(self._write_to.close)
 
789
        self._read_from.close()
 
790
        self._write_to.close()
789
791
        self._ssh_connection.close()
790
792
        self._connected = False
791
793
 
814
816
        if not self._connected:
815
817
            raise errors.MediumNotConnected(self)
816
818
        bytes_to_read = min(count, _MAX_READ_SIZE)
817
 
        bytes = osutils.until_no_eintr(self._read_from.read, bytes_to_read)
 
819
        bytes = self._read_from.read(bytes_to_read)
818
820
        self._report_activity(len(bytes), 'read')
819
821
        return bytes
820
822
 
844
846
        """See SmartClientMedium.disconnect()."""
845
847
        if not self._connected:
846
848
            return
847
 
        osutils.until_no_eintr(self._socket.close)
 
849
        self._socket.close()
848
850
        self._socket = None
849
851
        self._connected = False
850
852
 
898
900
        """See SmartClientMedium.read_bytes."""
899
901
        if not self._connected:
900
902
            raise errors.MediumNotConnected(self)
901
 
        return _read_bytes_from_socket(
902
 
            self._socket.recv, count, self._report_activity)
 
903
        return osutils.read_bytes_from_socket(
 
904
            self._socket, self._report_activity)
903
905
 
904
906
 
905
907
class SmartClientStreamMediumRequest(SmartClientMediumRequest):
942
944
        self._medium._flush()
943
945
 
944
946
 
945
 
def _read_bytes_from_socket(sock, desired_count, report_activity):
946
 
    # We ignore the desired_count because on sockets it's more efficient to
947
 
    # read large chunks (of _MAX_READ_SIZE bytes) at a time.
948
 
    try:
949
 
        bytes = osutils.until_no_eintr(sock, _MAX_READ_SIZE)
950
 
    except socket.error, e:
951
 
        if len(e.args) and e.args[0] in (errno.ECONNRESET, 10054):
952
 
            # The connection was closed by the other side.  Callers expect an
953
 
            # empty string to signal end-of-stream.
954
 
            bytes = ''
955
 
        else:
956
 
            raise
957
 
    else:
958
 
        report_activity(len(bytes), 'read')
959
 
    return bytes
960