diff options
-rw-r--r-- | src/cls/rgw/cls_rgw.cc | 24 | ||||
-rw-r--r-- | src/test/cls_rgw/test_cls_rgw.cc | 64 |
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) { |