Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

rgw/sfs: Fix list-objects check for common-prefixes #260

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions qa/rgw/store/sfs/tests/test-sfs-list-objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def check_list_response_prefix(self, list_resp, objects_expected, prefix, common
self.assertTrue(common_prefix["Prefix"] in common_prefixes)
else:
self.assertFalse("CommonPrefixes" in list_resp)
self.assertFalse(list_resp["IsTruncated"])


def test_list_objects_no_prefix(self):
Expand Down Expand Up @@ -260,6 +261,29 @@ def test_list_objects_with_delimiter(self):
]
self.check_list_response_prefix(objs_ret, expected_objects, 'directory/', expected_common_prefixes)

def test_list_objects_with_delimiter_object_name_is_greater(self):
bucket_name = self.get_random_bucket_name()
self.s3_client.create_bucket(Bucket=bucket_name)
self.assert_bucket_exists(bucket_name)
# objects to upload
objects = [
'b/test',
'test',
'test1',
'test2'
]
for obj in objects:
self.upload_file_and_check(bucket_name, obj)
# list all objects with prefix equal to 'prefix'
objs_ret = self.s3_client.list_objects(Bucket=bucket_name, Prefix='', Delimiter = '/')
expected_objects = [
'test', 'test1', 'test2'
]
expected_common_prefixes = [
'b/'
]
self.check_list_response_prefix(objs_ret, expected_objects, '', expected_common_prefixes)

if __name__ == '__main__':
if len(sys.argv) == 2:
address_port = sys.argv.pop()
Expand Down
4 changes: 2 additions & 2 deletions src/rgw/driver/sfs/bucket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ int SFSBucket::list(

if (!params.delim.empty()) {
std::vector<rgw_bucket_dir_entry> new_results;
list.roll_up_common_prefixes(
auto next_marker = list.roll_up_common_prefixes(
params.prefix, params.delim, results.objs, results.common_prefixes,
new_results
);
Expand All @@ -254,7 +254,7 @@ int SFSBucket::list(
// anything after the prefix.
if (!results.common_prefixes.empty()) {
std::vector<rgw_bucket_dir_entry> objects_after;
std::string query = std::prev(results.common_prefixes.end())->first;
std::string query = next_marker;
query.append(
sfs::S3_MAX_OBJECT_NAME_BYTES - query.size(),
std::numeric_limits<char>::max()
Expand Down
9 changes: 7 additions & 2 deletions src/rgw/driver/sfs/sqlite/sqlite_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,18 @@ bool SQLiteList::versions(
return true;
}

void SQLiteList::roll_up_common_prefixes(
std::string SQLiteList::roll_up_common_prefixes(
const std::string& find_after_prefix, const std::string& delimiter,
const std::vector<rgw_bucket_dir_entry>& objects,
std::map<std::string, bool>& out_common_prefixes,
std::vector<rgw_bucket_dir_entry>& out_objects
) const {
const size_t find_after_pos = find_after_prefix.length();
const size_t delim_len = delimiter.length();
std::string next_marker = "";
if (delimiter.empty()) {
out_objects = objects;
return;
return "";
}
const std::string* prefix{nullptr}; // Last added prefix
for (size_t i = 0; i < objects.size(); i++) {
Expand All @@ -181,12 +182,16 @@ void SQLiteList::roll_up_common_prefixes(
prefix = &out_common_prefixes
.emplace(name.substr(0, delim_pos + delim_len), true)
.first->first;
next_marker = *prefix;
continue;
}
}
// Not found -> next
out_objects.push_back(objects[i]);
next_marker = objects[i].key.name;
}

return next_marker;
}

} // namespace rgw::sal::sfs::sqlite
3 changes: 2 additions & 1 deletion src/rgw/driver/sfs/sqlite/sqlite_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class SQLiteList {
// `delimiter` position.
//
// Copy all other `objects` to `out_objects`.
void roll_up_common_prefixes(
// Returns the next marker to be used in a subsequent call to list objects
std::string roll_up_common_prefixes(
const std::string& find_after_prefix, const std::string& delimiter,
const std::vector<rgw_bucket_dir_entry>& objects,
std::map<std::string, bool>& out_common_prefixes,
Expand Down
Loading