diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py index e7af91ffd4..e7bd572fca 100644 --- a/swift/proxy/controllers/obj.py +++ b/swift/proxy/controllers/obj.py @@ -1438,7 +1438,13 @@ class ECAppIter(object): # with an un-reconstructible list of fragments - so we'll # break out of the iter so WSGI can tear down the broken # connection. - if not all(fragments): + frags_with_data = sum([1 for f in fragments if f]) + if frags_with_data < len(fragments): + if frags_with_data > 0: + self.logger.warning( + 'Un-recoverable fragment rebuild. Only received ' + '%d/%d fragments for %r', frags_with_data, + len(fragments), quote(self.path)) break try: segment = self.policy.pyeclib_driver.decode(fragments) diff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py index 0ccf86249f..4bbef7e085 100644 --- a/test/unit/proxy/controllers/test_obj.py +++ b/test/unit/proxy/controllers/test_obj.py @@ -4920,9 +4920,9 @@ class TestECObjController(ECObjectControllerMixin, unittest.TestCase): # re-raise the ChunkReadTimeout and still want a txn-id with set_http_connect(*status_codes, body_iter=body_iter, headers=headers), \ - mock.patch( - 'swift.proxy.controllers.obj.ECFragGetter.fast_forward', - side_effect=ValueError()): + mock.patch( + 'swift.proxy.controllers.obj.ECFragGetter.fast_forward', + side_effect=ValueError()): resp = req.get_response(self.app) self.assertEqual(resp.status_int, 200) self.assertNotEqual(md5(resp.body).hexdigest(), etag) @@ -4930,7 +4930,13 @@ class TestECObjController(ECObjectControllerMixin, unittest.TestCase): self.assertEqual(2, len(error_lines)) self.assertIn('Unable to fast forward', error_lines[0]) self.assertIn('Timeout fetching', error_lines[1]) - for line in self.logger.logger.records['ERROR']: + warning_lines = self.logger.get_lines_for_level('warning') + self.assertEqual(1, len(warning_lines)) + self.assertIn( + 'Un-recoverable fragment rebuild. Only received 9/10 fragments', + warning_lines[0]) + for line in self.logger.logger.records['ERROR'] + \ + self.logger.logger.records['WARNING']: self.assertIn(req.headers['x-trans-id'], line) def test_GET_read_timeout_resume_mixed_etag(self):