summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-10-03 02:04:22 +0000
committerGerrit Code Review <review@openstack.org>2015-10-03 02:04:23 +0000
commitab78b2409a0c21aab783ce184fadda32bab9d8b3 (patch)
tree6881ed2da6b59876d81dc4f3bf82ab765c721e99
parentc799d4de5296056b06e08d8025488472cfcb7d66 (diff)
parenta31ee07bda1a5ba8034277af9647aa21ad10be32 (diff)
downloadswift-ab78b2409a0c21aab783ce184fadda32bab9d8b3.tar.gz
Merge "Make sure we have enough .durable's for GETs"
-rw-r--r--swift/proxy/controllers/obj.py12
-rwxr-xr-xtest/unit/proxy/controllers/test_obj.py24
2 files changed, 29 insertions, 7 deletions
diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py
index c67edd8a4..bdb2028f3 100644
--- a/swift/proxy/controllers/obj.py
+++ b/swift/proxy/controllers/obj.py
@@ -2443,10 +2443,14 @@ class ECObjectController(BaseObjectController):
final_phase = True
need_quorum = False
# The .durable file will propagate in a replicated fashion; if
- # one exists, the reconstructor will spread it around. Thus, we
- # require "parity + 1" .durable files to be successfully written
- # as we do fragment archives in order to call the PUT a success.
- min_conns = policy.ec_nparity + 1
+ # one exists, the reconstructor will spread it around.
+ # In order to avoid successfully writing an object, but refusing
+ # to serve it on a subsequent GET because don't have enough
+ # durable data fragments - we require the same number of durable
+ # writes as quorum fragment writes. If object servers are in the
+ # future able to serve their non-durable fragment archives we may
+ # be able to reduce this quorum count if needed.
+ min_conns = policy.quorum
putters = [p for p in putters if not p.failed]
# ignore response etags, and quorum boolean
statuses, reasons, bodies, _etags, _quorum = \
diff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py
index b7143d789..da3abd0c8 100755
--- a/test/unit/proxy/controllers/test_obj.py
+++ b/test/unit/proxy/controllers/test_obj.py
@@ -2108,7 +2108,8 @@ class TestECObjController(BaseObjectControllerMixin, unittest.TestCase):
codes = [FakeStatus(201, response_sleep=response_sleep)
for i in range(self.replicas())]
# swap out some with regular fast responses
- number_of_fast_responses_needed_to_be_quick_enough = 5
+ number_of_fast_responses_needed_to_be_quick_enough = \
+ self.policy.quorum
fast_indexes = random.sample(
range(self.replicas()),
number_of_fast_responses_needed_to_be_quick_enough)
@@ -2125,12 +2126,29 @@ class TestECObjController(BaseObjectControllerMixin, unittest.TestCase):
self.assertEqual(resp.status_int, 201)
self.assertTrue(response_time < response_sleep)
+ def test_PUT_with_just_enough_durable_responses(self):
+ req = swift.common.swob.Request.blank('/v1/a/c/o', method='PUT',
+ body='')
+
+ codes = [201] * (self.policy.ec_ndata + 1)
+ codes += [503] * (self.policy.ec_nparity - 1)
+ self.assertEqual(len(codes), self.replicas())
+ random.shuffle(codes)
+ expect_headers = {
+ 'X-Obj-Metadata-Footer': 'yes',
+ 'X-Obj-Multiphase-Commit': 'yes'
+ }
+ with set_http_connect(*codes, expect_headers=expect_headers):
+ resp = req.get_response(self.app)
+ self.assertEqual(resp.status_int, 201)
+
def test_PUT_with_less_durable_responses(self):
req = swift.common.swob.Request.blank('/v1/a/c/o', method='PUT',
body='')
- codes = [201] * self.policy.ec_nparity
- codes += [503] * (self.policy.ec_ndata - 1)
+ codes = [201] * (self.policy.ec_ndata)
+ codes += [503] * (self.policy.ec_nparity)
+ self.assertEqual(len(codes), self.replicas())
random.shuffle(codes)
expect_headers = {
'X-Obj-Metadata-Footer': 'yes',