From: Xinying Song Date: Fri, 1 Dec 2017 05:58:50 +0000 (+0800) Subject: cls_rgw: use more effective container operations in get_obj_vals X-Git-Tag: v12.2.8~81^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1668d3b3444b4623b11bcfb774d08297c47fa8f9;p=ceph.git cls_rgw: use more effective container operations in get_obj_vals Signed-off-by: Xinying Song (cherry picked from commit 98c6eec544e104221b89ec0041efc84429e9f762) --- diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc index d7deb78f8b6f..c24405a669c7 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::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::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 old_keys; - old_keys.swap(*pkeys); + auto comp = [](const pair& l, const string &r) { return l.first < r; }; + string new_start = {static_cast(BI_PREFIX_CHAR + 1)}; - for (map::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(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 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::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 64c950eab885..13a93a5b2d53 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(0x41) }, + /* double byte utf8 character */ + { static_cast(0xCF), static_cast(0x8F) }, + /* treble byte utf8 character */ + { static_cast(0xDF), static_cast(0x8F), static_cast(0x8F) }, + /* quadruble byte utf8 character */ + { static_cast(0xF7), static_cast(0x8F), static_cast(0x8F), static_cast(0x8F) }, + /* BI_PREFIX_CHAR private namespace, for test only */ + { static_cast(0x80), static_cast(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 oids = { {0, bucket_oid} }; + map 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) {