From 315af1737be9a017a06634ae5f5ab89352e89cb5 Mon Sep 17 00:00:00 2001 From: Samuel Merritt Date: Fri, 5 Sep 2014 11:39:36 -0700 Subject: [PATCH] Error limit the right node on object PUT If any node had an error on object PUT, the proxy would count the error against the last-connected-to node instead of the one with the error. Now it counts the error against the right node. Change-Id: I884eb73cebe0c723473a6d5e390a148fcad0d3ed --- swift/proxy/controllers/obj.py | 8 +++++--- test/unit/proxy/test_server.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py index ec45c0739f..8d199b30c2 100644 --- a/swift/proxy/controllers/obj.py +++ b/swift/proxy/controllers/obj.py @@ -386,17 +386,19 @@ class ObjectController(Controller): try: with Timeout(self.app.node_timeout): if conn.resp: - return conn.resp + return (conn, conn.resp) else: - return conn.getresponse() + return (conn, conn.getresponse()) except (Exception, Timeout): self.app.exception_occurred( conn.node, _('Object'), _('Trying to get final status of PUT to %s') % req.path) + return (None, None) + pile = GreenAsyncPile(len(conns)) for conn in conns: pile.spawn(get_conn_response, conn) - for response in pile: + for (conn, response) in pile: if response: statuses.append(response.status) reasons.append(response.reason) diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 2882347dfb..4c59565521 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -2608,6 +2608,23 @@ class TestObjectController(unittest.TestCase): (200, 200, 200, 204, 204, 204), 503, raise_exc=True) + def test_PUT_error_limiting(self): + with save_globals(): + controller = proxy_server.ObjectController(self.app, 'account', + 'container', 'object') + controller.app.sort_nodes = lambda l: l + object_ring = controller.app.get_object_ring(None) + self.assert_status_map(controller.PUT, (200, 200, 503, 200, 200), + 200) + + # 2, not 1, because assert_status_map() calls the method twice + self.assertEquals(object_ring.devs[0].get('errors', 0), 2) + self.assertEquals(object_ring.devs[1].get('errors', 0), 0) + self.assertEquals(object_ring.devs[2].get('errors', 0), 0) + self.assert_('last_error' in object_ring.devs[0]) + self.assert_('last_error' not in object_ring.devs[1]) + self.assert_('last_error' not in object_ring.devs[2]) + def test_acc_or_con_missing_returns_404(self): with save_globals(): self.app.memcache = FakeMemcacheReturnsNone()