From: Yehuda Sadeh Date: Thu, 20 Jun 2013 03:19:39 +0000 (-0700) Subject: cls_rgw: skip namespaced entries when listing bucket X-Git-Tag: v0.67-rc1~128^2~69 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7b5ec743f03a16bd9a901b754fcb64598e7d6b17;p=ceph.git 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 --- diff --git a/src/cls/rgw/cls_rgw.cc b/src/cls/rgw/cls_rgw.cc index 40394650e28a..a75313b95da3 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;