From 6151c6c45da481c0ea9a4fb876d14b39c1e347bf Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Mon, 24 Aug 2015 20:36:22 +0000 Subject: [PATCH] Fix use of delimiter in account listings Previously, account listings that used the delimiter query param could omit some containers if they ended with the character that follows the delimiter. See If196e3075612b121ef8da4a9128167d00a248c27 for the corresponding fix for container listings. Change-Id: I57fcb97e51f653f5f4e306a632fcb3a0fb148c4e --- swift/account/backend.py | 12 ++++++++++-- test/unit/account/test_backend.py | 15 ++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/swift/account/backend.py b/swift/account/backend.py index 3e3947f565..c91f37fe9b 100644 --- a/swift/account/backend.py +++ b/swift/account/backend.py @@ -380,6 +380,7 @@ class AccountBroker(DatabaseBroker): :returns: list of tuples of (name, object_count, bytes_used, 0) """ + delim_force_gte = False (marker, end_marker, prefix, delimiter) = utf8encode( marker, end_marker, prefix, delimiter) self._commit_puts_stale_ok() @@ -392,12 +393,17 @@ class AccountBroker(DatabaseBroker): query = """ SELECT name, object_count, bytes_used, 0 FROM container - WHERE deleted = 0 AND """ + WHERE """ query_args = [] if end_marker: query += ' name < ? AND' query_args.append(end_marker) - if marker and marker >= prefix: + if delim_force_gte: + query += ' name >= ? AND' + query_args.append(marker) + # Always set back to False + delim_force_gte = False + elif marker and marker >= prefix: query += ' name > ? AND' query_args.append(marker) elif prefix: @@ -437,6 +443,8 @@ class AccountBroker(DatabaseBroker): end = name.find(delimiter, len(prefix)) if end > 0: marker = name[:end] + chr(ord(delimiter) + 1) + # we want result to be inclusive of delim+1 + delim_force_gte = True dir_name = name[:end + 1] if dir_name != orig_marker: results.append([dir_name, 0, 0, 1]) diff --git a/test/unit/account/test_backend.py b/test/unit/account/test_backend.py index 5571b50e15..8226195484 100644 --- a/test/unit/account/test_backend.py +++ b/test/unit/account/test_backend.py @@ -486,6 +486,11 @@ class TestAccountBroker(unittest.TestCase): POLICIES.default.idx) broker.put_container('a-b', Timestamp(time()).internal, 0, 0, 0, POLICIES.default.idx) + # NB: ord(".") == ord("-") + 1 + broker.put_container('a.', Timestamp(time()).internal, 0, 0, 0, + POLICIES.default.idx) + broker.put_container('a.b', Timestamp(time()).internal, 0, 0, 0, + POLICIES.default.idx) broker.put_container('b', Timestamp(time()).internal, 0, 0, 0, POLICIES.default.idx) broker.put_container('b-a', Timestamp(time()).internal, 0, 0, 0, @@ -495,20 +500,16 @@ class TestAccountBroker(unittest.TestCase): broker.put_container('c', Timestamp(time()).internal, 0, 0, 0, POLICIES.default.idx) listing = broker.list_containers_iter(15, None, None, None, None) - self.assertEqual(len(listing), 10) self.assertEqual([row[0] for row in listing], - ['a', 'a-', 'a-a', 'a-a-a', 'a-a-b', 'a-b', 'b', - 'b-a', 'b-b', 'c']) + ['a', 'a-', 'a-a', 'a-a-a', 'a-a-b', 'a-b', 'a.', + 'a.b', 'b', 'b-a', 'b-b', 'c']) listing = broker.list_containers_iter(15, None, None, '', '-') - self.assertEqual(len(listing), 5) self.assertEqual([row[0] for row in listing], - ['a', 'a-', 'b', 'b-', 'c']) + ['a', 'a-', 'a.', 'a.b', 'b', 'b-', 'c']) listing = broker.list_containers_iter(15, None, None, 'a-', '-') - self.assertEqual(len(listing), 4) self.assertEqual([row[0] for row in listing], ['a-', 'a-a', 'a-a-', 'a-b']) listing = broker.list_containers_iter(15, None, None, 'b-', '-') - self.assertEqual(len(listing), 2) self.assertEqual([row[0] for row in listing], ['b-a', 'b-b']) def test_chexor(self):