From 9c4f9856b034061aed052192b0ee09b9a9d09bc0 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 6 Sep 2017 16:14:58 -0400 Subject: [PATCH] rbd: support iterating over metadata items when listing Fixes: http://tracker.ceph.com/issues/21179 Signed-off-by: Jason Dillaman --- src/tools/rbd/action/ImageMeta.cc | 78 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/src/tools/rbd/action/ImageMeta.cc b/src/tools/rbd/action/ImageMeta.cc index 4664f770dc9..58f2db5979d 100644 --- a/src/tools/rbd/action/ImageMeta.cc +++ b/src/tools/rbd/action/ImageMeta.cc @@ -33,52 +33,66 @@ int get_key(const po::variables_map &vm, std::string *key) { return 0; } +const uint32_t MAX_KEYS = 64; + } // anonymous namespace static int do_metadata_list(librbd::Image& image, Formatter *f) { - std::map pairs; int r; TextTable tbl; - r = image.metadata_list("", 0, &pairs); - if (r < 0) { - std::cerr << "failed to list metadata of image : " << cpp_strerror(r) - << std::endl; - return r; - } - - if (f) { - f->open_object_section("metadatas"); - } else { - tbl.define_column("Key", TextTable::LEFT, TextTable::LEFT); - tbl.define_column("Value", TextTable::LEFT, TextTable::LEFT); - } + size_t count = 0; + std::string last_key; + bool more_results = true; + while (more_results) { + std::map pairs; + r = image.metadata_list(last_key, MAX_KEYS, &pairs); + if (r < 0) { + std::cerr << "failed to list metadata of image : " << cpp_strerror(r) + << std::endl; + return r; + } - if (!pairs.empty()) { - bool one = (pairs.size() == 1); + more_results = (pairs.size() == MAX_KEYS); + if (!pairs.empty()) { + if (count == 0) { + if (f) { + f->open_object_section("metadatas"); + } else { + tbl.define_column("Key", TextTable::LEFT, TextTable::LEFT); + tbl.define_column("Value", TextTable::LEFT, TextTable::LEFT); + } + } - if (!f) { - std::cout << "There " << (one ? "is " : "are ") << pairs.size() - << " metadata" << (one ? "" : "s") << " on this image.\n"; - } + last_key = pairs.rbegin()->first; + count += pairs.size(); - for (std::map::iterator it = pairs.begin(); - it != pairs.end(); ++it) { - std::string val(it->second.c_str(), it->second.length()); - if (f) { - f->dump_string(it->first.c_str(), val.c_str()); - } else { - tbl << it->first << val.c_str() << TextTable::endrow; + for (auto kv : pairs) { + std::string val(kv.second.c_str(), kv.second.length()); + if (f) { + f->dump_string(kv.first.c_str(), val.c_str()); + } else { + tbl << kv.first << val << TextTable::endrow; + } } } - if (!f) - std::cout << tbl; } - if (f) { - f->close_section(); - f->flush(std::cout); + if (f == nullptr) { + bool single = (count == 1); + std::cout << "There " << (single ? "is" : "are") << " " << count << " " + << (single ? "metadatum" : "metadata") << " on this image" + << (count == 0 ? "." : ":") << std::endl; + } + + if (count > 0) { + if (f) { + f->close_section(); + f->flush(std::cout); + } else { + std::cout << std::endl << tbl; + } } return 0; } -- 2.39.5