summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cls/rgw/cls_rgw.cc24
-rw-r--r--src/test/cls_rgw/test_cls_rgw.cc64
2 files changed, 73 insertions, 15 deletions
diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc
index ba3d4c4bb1b..65d22a1bd7e 100644
--- a/src/cls/rgw/cls_rgw.cc
+++ b/src/cls/rgw/cls_rgw.cc
@@ -154,43 +154,37 @@ static int get_obj_vals(cls_method_context_t hctx, const string& start, const st
if (pkeys->empty())
return 0;
- map<string, bufferlist>::reverse_iterator last_element = pkeys->rbegin();
+ auto last_element = pkeys->rbegin();
if ((unsigned char)last_element->first[0] < BI_PREFIX_CHAR) {
/* nothing to see here, move along */
return 0;
}
- map<string, bufferlist>::iterator first_element = pkeys->begin();
+ auto first_element = pkeys->begin();
if ((unsigned char)first_element->first[0] > BI_PREFIX_CHAR) {
return 0;
}
/* let's rebuild the list, only keep entries we're interested in */
- map<string, bufferlist> old_keys;
- old_keys.swap(*pkeys);
+ auto comp = [](const pair<string, bufferlist>& l, const string &r) { return l.first < r; };
+ string new_start = {static_cast<char>(BI_PREFIX_CHAR + 1)};
- for (map<string, bufferlist>::iterator iter = old_keys.begin(); iter != old_keys.end(); ++iter) {
- if ((unsigned char)iter->first[0] != BI_PREFIX_CHAR) {
- (*pkeys)[iter->first] = iter->second;
- }
- }
+ auto lower = pkeys->lower_bound(string{static_cast<char>(BI_PREFIX_CHAR)});
+ auto upper = std::lower_bound(lower, pkeys->end(), new_start, comp);
+ pkeys->erase(lower, upper);
if (num_entries == (int)pkeys->size())
return 0;
map<string, bufferlist> new_keys;
- char c[] = { (char)(BI_PREFIX_CHAR + 1), 0 };
- string new_start = c;
/* now get some more keys */
ret = cls_cxx_map_get_vals(hctx, new_start, filter_prefix, num_entries - pkeys->size(), &new_keys, pmore);
if (ret < 0)
return ret;
- for (map<string, bufferlist>::iterator iter = new_keys.begin(); iter != new_keys.end(); ++iter) {
- (*pkeys)[iter->first] = iter->second;
- }
-
+ pkeys->insert(std::make_move_iterator(new_keys.begin()),
+ std::make_move_iterator(new_keys.end()));
return 0;
}
diff --git a/src/test/cls_rgw/test_cls_rgw.cc b/src/test/cls_rgw/test_cls_rgw.cc
index 6c7dbaf5235..a2b1eeddbb3 100644
--- a/src/test/cls_rgw/test_cls_rgw.cc
+++ b/src/test/cls_rgw/test_cls_rgw.cc
@@ -375,6 +375,70 @@ TEST(cls_rgw, index_suggest)
test_stats(ioctx, bucket_oid, 0, num_objs / 2, total_size);
}
+/*
+ * This case is used to test whether get_obj_vals will
+ * return all validate utf8 objnames and filter out those
+ * in BI_PREFIX_CHAR private namespace.
+ */
+TEST(cls_rgw, index_list)
+{
+ string bucket_oid = str_int("bucket", 4);
+
+ OpMgr mgr;
+
+ ObjectWriteOperation *op = mgr.write_op();
+ cls_rgw_bucket_init(*op);
+ ASSERT_EQ(0, ioctx.operate(bucket_oid, op));
+
+ uint64_t epoch = 1;
+ uint64_t obj_size = 1024;
+ const int num_objs = 5;
+ const string keys[num_objs] = {
+ /* single byte utf8 character */
+ { static_cast<char>(0x41) },
+ /* double byte utf8 character */
+ { static_cast<char>(0xCF), static_cast<char>(0x8F) },
+ /* treble byte utf8 character */
+ { static_cast<char>(0xDF), static_cast<char>(0x8F), static_cast<char>(0x8F) },
+ /* quadruble byte utf8 character */
+ { static_cast<char>(0xF7), static_cast<char>(0x8F), static_cast<char>(0x8F), static_cast<char>(0x8F) },
+ /* BI_PREFIX_CHAR private namespace, for test only */
+ { static_cast<char>(0x80), static_cast<char>(0x41) }
+ };
+
+ for (int i = 0; i < num_objs; i++) {
+ string obj = keys[i];
+ string tag = str_int("tag", i);
+ string loc = str_int("loc", i);
+
+ index_prepare(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, obj, loc);
+
+ op = mgr.write_op();
+ rgw_bucket_dir_entry_meta meta;
+ meta.category = 0;
+ meta.size = obj_size;
+ index_complete(mgr, ioctx, bucket_oid, CLS_RGW_OP_ADD, tag, epoch, obj, meta);
+ }
+
+ test_stats(ioctx, bucket_oid, 0, num_objs, obj_size * num_objs);
+
+ map<int, string> oids = { {0, bucket_oid} };
+ map<int, struct rgw_cls_list_ret> list_results;
+ cls_rgw_obj_key start_key("", "");
+ int r = CLSRGWIssueBucketList(ioctx, start_key, "", 1000, true, oids, list_results, 1)();
+
+ ASSERT_EQ(r, 0);
+ ASSERT_EQ(1, list_results.size());
+
+ auto it = list_results.begin();
+ auto m = (it->second).dir.m;
+
+ ASSERT_EQ(4, m.size());
+ int i = 0;
+ for(auto it2 = m.begin(); it2 != m.end(); it2++, i++)
+ ASSERT_EQ(it2->first.compare(keys[i]), 0);
+}
+
/* test garbage collection */
static void create_obj(cls_rgw_obj& obj, int i, int j)
{