From 7b5ec743f03a16bd9a901b754fcb64598e7d6b17 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Wed, 19 Jun 2013 20:19:39 -0700 Subject: cls_rgw: skip namespaced entries when listing bucket We added a namespace to the entries, and sadly there can be valid entries beyond it. Previously we assumed that once we encounter the namespace tag we're done. That was wrong. We need to skip the namespace and continue the listing from there. Signed-off-by: Yehuda Sadeh --- src/cls/rgw/cls_rgw.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc index 40394650e28..a75313b95da 100644 --- a/src/cls/rgw/cls_rgw.cc +++ b/src/cls/rgw/cls_rgw.cc @@ -130,6 +130,59 @@ static int log_index_operation(cls_method_context_t hctx, string& obj, RGWModify return cls_cxx_map_set_val(hctx, key, &bl); } +/* + * read list of objects, skips objects in the ugly namespace + */ +static int get_obj_vals(cls_method_context_t hctx, const string& start, const string& filter_prefix, + int num_entries, map *pkeys) +{ + int ret = cls_cxx_map_get_vals(hctx, start, filter_prefix, num_entries, pkeys); + if (ret < 0) + return ret; + + if (pkeys->empty()) + return 0; + + map::reverse_iterator 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(); + 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); + + 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; + } + } + + if (num_entries == (int)pkeys->size()) + return 0; + + map new_keys; + char c[] = { 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); + if (ret < 0) + return ret; + + for (map::iterator iter = new_keys.begin(); iter != new_keys.end(); ++iter) { + (*pkeys)[iter->first] = iter->second; + } + + return 0; +} + int rgw_bucket_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out) { bufferlist::iterator iter = in->begin(); @@ -159,7 +212,7 @@ int rgw_bucket_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out) bufferlist bl; map keys; - rc = cls_cxx_map_get_vals(hctx, op.start_obj, op.filter_prefix, op.num_entries + 1, &keys); + rc = get_obj_vals(hctx, op.start_obj, op.filter_prefix, op.num_entries + 1, &keys); if (rc < 0) return rc; @@ -222,7 +275,7 @@ static int check_index(cls_method_context_t hctx, struct rgw_bucket_dir_header * bool done = false; do { - rc = cls_cxx_map_get_vals(hctx, start_obj, filter_prefix, CHECK_CHUNK_SIZE, &keys); + rc = get_obj_vals(hctx, start_obj, filter_prefix, CHECK_CHUNK_SIZE, &keys); if (rc < 0) return rc; -- cgit v1.2.1