summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKota Tsuyuzaki <tsuyuzaki.kota@lab.ntt.co.jp>2015-04-20 00:18:25 -0700
committerJohn Dickinson <me@not.mn>2015-04-21 11:29:36 -0700
commitcd7c58e93690fd25f5266754d0593c656dd51e2e (patch)
treea9538f79341fcc9596267b6d74db6d0575779b4a
parent281cb1c210f0292bad190cabaae447145fa5eade (diff)
downloadswift-cd7c58e93690fd25f5266754d0593c656dd51e2e.tar.gz
Use reconstruct insetad of decode/encode
With bumping PyECLib up to 1.0.7 on global requirements, we can use the "reconstruct" function directly instead of the current hack doing decode/encode on reconstructor. That is because the hack was for treating PyECLib < 1.0.7 (strictly jearsure scheme) reconstruction bug so we don't have to do decode/encode anymore. Closes-Bug: 1446801 Co-Authored-By: Clay Gerrard <clay.gerrard@gmail.com> Change-Id: I69aae495670e3d0bdebe665f73915547a4d56f99
-rw-r--r--swift/obj/reconstructor.py10
-rwxr-xr-xtest/unit/obj/test_reconstructor.py39
2 files changed, 41 insertions, 8 deletions
diff --git a/swift/obj/reconstructor.py b/swift/obj/reconstructor.py
index db078de2f..4385e42cc 100644
--- a/swift/obj/reconstructor.py
+++ b/swift/obj/reconstructor.py
@@ -276,14 +276,8 @@ class ObjectReconstructor(Daemon):
rebuilt_fragment_iter)
def _reconstruct(self, policy, fragment_payload, frag_index):
- # XXX with jerasure this doesn't work if we need to rebuild a
- # parity fragment, and not all data fragments are available
- # segment = policy.pyeclib_driver.reconstruct(
- # fragment_payload, [frag_index])[0]
-
- # for safety until pyeclib 1.0.7 we'll just use decode and encode
- segment = policy.pyeclib_driver.decode(fragment_payload)
- return policy.pyeclib_driver.encode(segment)[frag_index]
+ return policy.pyeclib_driver.reconstruct(fragment_payload,
+ [frag_index])[0]
def make_rebuilt_fragment_iter(self, responses, path, policy, frag_index):
"""
diff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py
index b7254f434..23e70543f 100755
--- a/test/unit/obj/test_reconstructor.py
+++ b/test/unit/obj/test_reconstructor.py
@@ -2347,6 +2347,45 @@ class TestObjectReconstructor(unittest.TestCase):
self.assertEqual(md5(fixed_body).hexdigest(),
md5(broken_body).hexdigest())
+ def test_reconstruct_parity_fa_with_data_node_failure(self):
+ job = {
+ 'partition': 0,
+ 'policy': self.policy,
+ }
+ part_nodes = self.policy.object_ring.get_part_nodes(0)
+ node = part_nodes[-4]
+ metadata = {
+ 'name': '/a/c/o',
+ 'Content-Length': 0,
+ 'ETag': 'etag',
+ }
+
+ # make up some data (trim some amount to make it unaligned with
+ # segment size)
+ test_data = ('rebuild' * self.policy.ec_segment_size)[:-454]
+ etag = md5(test_data).hexdigest()
+ ec_archive_bodies = make_ec_archive_bodies(self.policy, test_data)
+
+ # the scheme is 10+4, so this gets a parity node
+ broken_body = ec_archive_bodies.pop(-4)
+
+ base_responses = list((200, body) for body in ec_archive_bodies)
+ for error in (Timeout(), 404, Exception('kaboom!')):
+ responses = list(base_responses)
+ # grab a data node index
+ error_index = random.randint(0, self.policy.ec_ndata - 1)
+ responses[error_index] = (error, '')
+ headers = {'X-Object-Sysmeta-Ec-Etag': etag}
+ codes, body_iter = zip(*responses)
+ with mocked_http_conn(*codes, body_iter=body_iter,
+ headers=headers):
+ df = self.reconstructor.reconstruct_fa(
+ job, node, dict(metadata))
+ fixed_body = ''.join(df.reader())
+ self.assertEqual(len(fixed_body), len(broken_body))
+ self.assertEqual(md5(fixed_body).hexdigest(),
+ md5(broken_body).hexdigest())
+
def test_reconstruct_fa_errors_fails(self):
job = {
'partition': 0,