Rev 5138: Merge 2.1-all-reconnect-819604 and resolve conflicts. in http://bazaar.launchpad.net/~jameinel/bzr/2.2-all-reconnect-819604
John Arbash Meinel
john at arbash-meinel.com
Fri Sep 14 07:09:10 UTC 2012
At http://bazaar.launchpad.net/~jameinel/bzr/2.2-all-reconnect-819604
------------------------------------------------------------
revno: 5138 [merge]
revision-id: john at arbash-meinel.com-20120914070833-om0l2637zl7u1vg3
parent: john at arbash-meinel.com-20120914065845-vrkcct69mr1n3gty
parent: john at arbash-meinel.com-20120912092637-7kop15ivhav2jh3y
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.2-all-reconnect-819604
timestamp: Fri 2012-09-14 11:08:33 +0400
message:
Merge 2.1-all-reconnect-819604 and resolve conflicts.
Most of the failures are just from copyright and import headers.
The code is now closer to the 2.5 version, since it has the AlreadyConnected medium.
modified:
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/smart/medium.py medium.py-20061103051856-rgu2huy59fkz902q-1
bzrlib/smart/protocol.py protocol.py-20061108035435-ot0lstk2590yqhzr-1
bzrlib/smart/request.py request.py-20061108095550-gunadhxmzkdjfeek-1
bzrlib/tests/test_bundle.py test.py-20050630184834-092aa401ab9f039c
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
-------------- next part --------------
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py 2011-10-10 13:36:30 +0000
+++ b/bzrlib/osutils.py 2012-09-14 07:08:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2010 Canonical Ltd
+# Copyright (C) 2005-2012 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
# and need the former on windows
import shutil
from shutil import rmtree
+import signal
import socket
import subprocess
# We need to import both tempfile and mkdtemp as we export the later on posix
@@ -1993,8 +1994,13 @@
# data at once.
MAX_SOCKET_CHUNK = 64 * 1024
-WSAECONNABORTED = 10053
-WSAECONNRESET = 10054
+_end_of_stream_errors = [errno.ECONNRESET, errno.EPIPE, errno.EINVAL]
+for _eno in ['WSAECONNRESET', 'WSAECONNABORTED']:
+ _eno = getattr(errno, _eno, None)
+ if _eno is not None:
+ _end_of_stream_errors.append(_eno)
+del _eno
+
def read_bytes_from_socket(sock, report_activity=None,
max_read_size=MAX_SOCKET_CHUNK):
@@ -2009,7 +2015,7 @@
bytes = sock.recv(max_read_size)
except socket.error, e:
eno = e.args[0]
- if eno in (errno.ECONNRESET, WSAECONNABORTED, WSAECONNRESET):
+ if eno in _end_of_stream_errors:
# The connection was closed by the other side. Callers expect
# an empty string to signal end-of-stream.
return ""
@@ -2060,12 +2066,19 @@
while sent_total < byte_count:
try:
sent = sock.send(buffer(bytes, sent_total, MAX_SOCKET_CHUNK))
- except socket.error, e:
+ except (socket.error, IOError), e:
+ if e.args[0] in _end_of_stream_errors:
+ raise errors.ConnectionReset(
+ "Error trying to write to socket", e)
if e.args[0] != errno.EINTR:
raise
else:
+ if sent == 0:
+ raise errors.ConnectionReset('Sending to %s returned 0 bytes'
+ % (sock,))
sent_total += sent
- report_activity(sent, 'write')
+ if report_activity is not None:
+ report_activity(sent, 'write')
def dereference_path(path):
=== modified file 'bzrlib/smart/medium.py'
--- a/bzrlib/smart/medium.py 2011-10-10 13:38:17 +0000
+++ b/bzrlib/smart/medium.py 2012-09-14 07:08:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2011 Canonical Ltd
+# Copyright (C) 2006-2012 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -177,6 +177,14 @@
ui.ui_factory.report_transport_activity(self, bytes, direction)
+_bad_file_descriptor = (errno.EBADF,)
+if sys.platform == 'win32':
+ # Given on Windows if you pass a closed socket to select.select. Probably
+ # also given if you pass a file handle to select.
+ WSAENOTSOCK = 10038
+ _bad_file_descriptor += (WSAENOTSOCK,)
+
+
class SmartServerStreamMedium(SmartMedium):
"""Handles smart commands coming over a stream.
@@ -240,6 +248,8 @@
:param protocol: a SmartServerRequestProtocol.
"""
+ if protocol is None:
+ return
try:
self._serve_one_request_unguarded(protocol)
except KeyboardInterrupt:
@@ -738,7 +748,7 @@
except IOError, e:
if e.errno in (errno.EINVAL, errno.EPIPE):
raise errors.ConnectionReset(
- "Error trying to write to subprocess:\n%s" % (e,))
+ "Error trying to write to subprocess", e)
raise
self._report_activity(len(bytes), 'write')
@@ -793,6 +803,7 @@
# method before calling the super init.
SmartClientStreamMedium.__init__(self, base)
self._vendor = vendor
+ self._bzr_remote_path = bzr_remote_path
self._ssh_connection = None
def __repr__(self):
@@ -915,6 +926,20 @@
SmartClientSocketMedium.__init__(self, base)
self._host = host
self._port = port
+ self._socket = None
+
+ def _accept_bytes(self, bytes):
+ """See SmartClientMedium.accept_bytes."""
+ self._ensure_connection()
+ osutils.send_all(self._socket, bytes, self._report_activity)
+
+ def disconnect(self):
+ """See SmartClientMedium.disconnect()."""
+ if not self._connected:
+ return
+ self._socket.close()
+ self._socket = None
+ self._connected = False
def _ensure_connection(self):
"""Connect this medium if not already connected."""
=== modified file 'bzrlib/smart/protocol.py'
--- a/bzrlib/smart/protocol.py 2011-10-10 13:38:17 +0000
+++ b/bzrlib/smart/protocol.py 2012-09-14 07:08:33 +0000
@@ -654,7 +654,7 @@
"""Make a remote call with a readv array.
The body is encoded with one line per readv offset pair. The numbers in
- each pair are separated by a comma, and no trailing \n is emitted.
+ each pair are separated by a comma, and no trailing \\n is emitted.
"""
if 'hpss' in debug.debug_flags:
mutter('hpss call w/readv: %s', repr(args)[1:-1])
@@ -1330,7 +1330,7 @@
"""Make a remote call with a readv array.
The body is encoded with one line per readv offset pair. The numbers in
- each pair are separated by a comma, and no trailing \n is emitted.
+ each pair are separated by a comma, and no trailing \\n is emitted.
"""
if 'hpss' in debug.debug_flags:
mutter('hpss call w/readv: %s', repr(args)[1:-1])
=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py 2011-10-10 13:36:30 +0000
+++ b/bzrlib/smart/request.py 2012-09-14 07:08:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2011 Canonical Ltd
+# Copyright (C) 2006-2012 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -134,7 +134,7 @@
It will return a SmartServerResponse if the command does not expect a
body.
- :param *args: the arguments of the request.
+ :param args: the arguments of the request.
"""
self._check_enabled()
return self.do(*args)
@@ -556,8 +556,8 @@
'Branch.set_parent_location', 'bzrlib.smart.branch',
'SmartServerBranchRequestSetParentLocation', info='idem')
request_handlers.register_lazy(
- 'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock',
- info='semi')
+ 'Branch.unlock', 'bzrlib.smart.branch',
+ 'SmartServerBranchRequestUnlock', info='semi')
request_handlers.register_lazy(
'BzrDir.cloning_metadir', 'bzrlib.smart.bzrdir',
'SmartServerBzrDirRequestCloningMetaDir', info='read')
@@ -680,5 +680,5 @@
request_handlers.register_lazy(
'stat', 'bzrlib.smart.vfs', 'StatRequest', info='read')
request_handlers.register_lazy(
- 'Transport.is_readonly', 'bzrlib.smart.request', 'SmartServerIsReadonly',
- info='read')
+ 'Transport.is_readonly', 'bzrlib.smart.request',
+ 'SmartServerIsReadonly', info='read')
=== modified file 'bzrlib/tests/test_bundle.py'
--- a/bzrlib/tests/test_bundle.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/tests/test_bundle.py 2012-09-14 07:08:33 +0000
@@ -1855,20 +1855,23 @@
self.sock.bind(('127.0.0.1', 0))
self.sock.listen(1)
self.port = self.sock.getsockname()[1]
+ self.stopping = threading.Event()
self.thread = threading.Thread(
name='%s (port %d)' % (self.__class__.__name__, self.port),
target=self.accept_and_close)
self.thread.start()
def accept_and_close(self):
- conn, addr = self.sock.accept()
- conn.shutdown(socket.SHUT_RDWR)
- conn.close()
+ while not self.stopping.isSet():
+ conn, addr = self.sock.accept()
+ conn.shutdown(socket.SHUT_RDWR)
+ conn.close()
def get_url(self):
return 'bzr://127.0.0.1:%d/' % (self.port,)
def stop_server(self):
+ self.stopping.set()
try:
# make sure the thread dies by connecting to the listening socket,
# just in case the test failed to do so.
=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py 2010-12-02 09:23:10 +0000
+++ b/bzrlib/tests/test_osutils.py 2012-09-14 07:08:33 +0000
@@ -804,6 +804,45 @@
self.assertEqual(None, osutils.safe_file_id(None))
+class TestSendAll(tests.TestCase):
+
+ def test_send_with_disconnected_socket(self):
+ class DisconnectedSocket(object):
+ def __init__(self, err):
+ self.err = err
+ def send(self, content):
+ raise self.err
+ def close(self):
+ pass
+ # All of these should be treated as ConnectionReset
+ errs = []
+ for err_cls in (IOError, socket.error):
+ for errnum in osutils._end_of_stream_errors:
+ errs.append(err_cls(errnum))
+ for err in errs:
+ sock = DisconnectedSocket(err)
+ self.assertRaises(errors.ConnectionReset,
+ osutils.send_all, sock, 'some more content')
+
+ def test_send_with_no_progress(self):
+ # See https://bugs.launchpad.net/bzr/+bug/1047309
+ # It seems that paramiko can get into a state where it doesn't error,
+ # but it returns 0 bytes sent for requests over and over again.
+ class NoSendingSocket(object):
+ def __init__(self):
+ self.call_count = 0
+ def send(self, bytes):
+ self.call_count += 1
+ if self.call_count > 100:
+ # Prevent the test suite from hanging
+ raise RuntimeError('too many calls')
+ return 0
+ sock = NoSendingSocket()
+ self.assertRaises(errors.ConnectionReset,
+ osutils.send_all, sock, 'content')
+ self.assertEqual(1, sock.call_count)
+
+
class TestWin32Funcs(tests.TestCase):
"""Test that _win32 versions of os utilities return appropriate paths."""
More information about the bazaar-commits
mailing list