Skip to content

Instantly share code, notes, and snippets.

@clayg
Created June 18, 2015 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clayg/4aebb0a21589d485785e to your computer and use it in GitHub Desktop.
Save clayg/4aebb0a21589d485785e to your computer and use it in GitHub Desktop.
diff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py
index 321ea37..ae3c155 100755
--- a/test/unit/obj/test_reconstructor.py
+++ b/test/unit/obj/test_reconstructor.py
@@ -24,6 +24,7 @@ import shutil
import re
import random
from eventlet import Timeout
+import struct
from contextlib import closing, nested, contextmanager
from gzip import GzipFile
@@ -2512,6 +2513,59 @@ class TestObjectReconstructor(unittest.TestCase):
self.assertRaises(DiskFileError, self.reconstructor.reconstruct_fa,
job, node, dict(metadata))
+ @patch_policies([ECStoragePolicy()])
+ def test_reconstruct_fa_finds_itself_does_not_blow_up(self):
+ """
+ On some backends if you ask to reconstruct a fragment that is in the
+ list of fragments you want to reconstruct from we were able to see
+ segfaults, in our code we prevent the reconstructor from excepting a
+ backend connection to an object server that has the same fragment
+ index we need to rebuild.
+
+ Other approach would be to abort the rebuild and move on to the next
+ object in the hopes that the remote who has the fragment we're trying
+ to rebuild will eventually push it over to the correct node.
+ """
+ job = {
+ 'partition': 0,
+ 'policy': self.policy,
+ }
+ part_nodes = self.policy.object_ring.get_part_nodes(0)
+ node = part_nodes[1]
+ metadata = {
+ 'name': '/a/c/o',
+ 'Content-Length': 0,
+ 'ETag': 'etag',
+ }
+
+ test_data = ('rebuild' * self.policy.ec_segment_size)[:-777]
+ etag = md5(test_data).hexdigest()
+ ec_archive_bodies = make_ec_archive_bodies(self.policy, test_data)
+
+ # instead of popping the broken body, we'll just lave it in the list
+ # of responses and take away something else.
+ broken_body = ec_archive_bodies[1]
+ ec_archive_bodies = ec_archive_bodies[:-1]
+
+ def make_header(body):
+ metadata = self.policy.pyeclib_driver.get_metadata(body)
+ frag_index = struct.unpack('h', metadata[:2])[0]
+ return {
+ 'X-Object-Sysmeta-Ec-Frag-Index': frag_index,
+ 'X-Object-Sysmeta-Ec-Etag': etag,
+ }
+
+ responses = [(200, body, make_header(body))
+ for body in ec_archive_bodies]
+ codes, body_iter, headers = zip(*responses)
+ with mocked_http_conn(*codes, body_iter=body_iter, headers=headers):
+ df = self.reconstructor.reconstruct_fa(
+ job, node, metadata)
+ fixed_body = ''.join(df.reader())
+ self.assertEqual(len(fixed_body), len(broken_body))
+ self.assertEqual(md5(fixed_body).hexdigest(),
+ md5(broken_body).hexdigest())
+
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment