From 09b7ed600bfda6f708db85cd850c0539c3448a0a Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Wed, 5 Feb 2020 08:36:24 -0800 Subject: [PATCH] sharding: filter shards based on prefix param when listing Otherwise, we make a bunch of backend requests where we have no real expectation of finding data. Change-Id: I7eaa012ba938eaa7fc22837c32007d1b7ae99709 --- swift/proxy/controllers/container.py | 13 ++++++++++ test/unit/proxy/controllers/test_container.py | 25 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/swift/proxy/controllers/container.py b/swift/proxy/controllers/container.py index 6ab0ada3a7..2235db757c 100644 --- a/swift/proxy/controllers/container.py +++ b/swift/proxy/controllers/container.py @@ -166,6 +166,7 @@ class ContainerController(Controller): reverse = config_true_value(params.get('reverse')) marker = wsgi_to_str(params.get('marker')) end_marker = wsgi_to_str(params.get('end_marker')) + prefix = wsgi_to_str(params.get('prefix')) limit = req_limit for shard_range in shard_ranges: @@ -200,6 +201,18 @@ class ContainerController(Controller): headers = {'X-Backend-Record-Type': 'object'} else: headers = None + + if prefix: + if prefix > shard_range: + continue + try: + just_past = prefix[:-1] + chr(ord(prefix[-1]) + 1) + except ValueError: + pass + else: + if just_past < shard_range: + continue + self.app.logger.debug('Getting from %s %s with %s', shard_range, shard_range.name, headers) objs, shard_resp = self._get_container_listing( diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py index b989fb6145..ba0e4fff1a 100644 --- a/test/unit/proxy/controllers/test_container.py +++ b/test/unit/proxy/controllers/test_container.py @@ -810,6 +810,31 @@ class TestContainerController(TestRingBase): query_string='?end_marker=%s' % end_marker) self.check_response(resp, root_resp_hdrs) + # GET with prefix + prefix = 'hat' + # they're all 1-character names; the important thing + # is which shards we query + expected_objects = [] + mock_responses = [ + (404, '', {}), + (200, sr_dicts, root_shard_resp_hdrs), + (200, [], shard_resp_hdrs[1]), + ] + expected_requests = [ + ('a/c', {'X-Backend-Record-Type': 'auto'}, + dict(prefix=prefix, states='listing')), # 404 + ('a/c', {'X-Backend-Record-Type': 'auto'}, + dict(prefix=prefix, states='listing')), # 200 + (wsgi_quote(str_to_wsgi(shard_ranges[1].name)), + {'X-Backend-Record-Type': 'auto'}, # 404 + dict(prefix=prefix, marker='', end_marker='pie\x00', + states='listing', limit=str(limit))), + ] + resp = self._check_GET_shard_listing( + mock_responses, expected_objects, expected_requests, + query_string='?prefix=%s' % prefix) + self.check_response(resp, root_resp_hdrs) + # marker and end_marker and limit limit = 2 expected_objects = all_objects[first_included:first_excluded]