From: Mykola Golub Date: Tue, 29 Sep 2015 06:24:24 +0000 (+0300) Subject: osd: pg_pool_t: add dictionary for pool options X-Git-Tag: v10.0.2~164^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=73077dd0b56b57253cf2475f7038104e7ae6c331;p=ceph.git osd: pg_pool_t: add dictionary for pool options It is going to be used to store per pool configuration parameters like scrub intervals or recovery priority. Signed-off-by: Mykola Golub --- diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index f3e970399c78..2fcb07d49d73 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -5087,6 +5087,41 @@ int OSDMonitor::prepare_command_pool_set(map &cmdmap, } else if (val == "false" || (interr.empty() && n == 0)) { p.fast_read = false; } + } else if (pool_opts_t::is_opt_name(var)) { + pool_opts_t::opt_desc_t desc = pool_opts_t::get_opt_desc(var); + switch (desc.type) { + case pool_opts_t::STR: + if (val.empty()) { + p.opts.unset(desc.key); + } else { + p.opts.set(desc.key, static_cast(val)); + } + break; + case pool_opts_t::INT: + if (interr.length()) { + ss << "error parsing integer value '" << val << "': " << interr; + return -EINVAL; + } + if (n == 0) { + p.opts.unset(desc.key); + } else { + p.opts.set(desc.key, static_cast(n)); + } + break; + case pool_opts_t::DOUBLE: + if (floaterr.length()) { + ss << "error parsing floating point value '" << val << "': " << floaterr; + return -EINVAL; + } + if (f == 0) { + p.opts.unset(desc.key); + } else { + p.opts.set(desc.key, static_cast(f)); + } + break; + default: + assert(!"unknown type"); + } } else { ss << "unrecognized variable '" << var << "'"; return -EINVAL; diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index 023ef818a6dd..8b54993c687a 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -15,6 +15,8 @@ * */ +#include + #include "osd_types.h" #include "include/ceph_features.h" extern "C" { @@ -889,6 +891,156 @@ void pool_snap_info_t::generate_test_instances(list& o) o.back()->name = "foo"; } +// -- pool_opts_t -- + +typedef std::map opt_mapping_t; +static opt_mapping_t opt_mapping; + +bool pool_opts_t::is_opt_name(const std::string& name) { + return opt_mapping.find(name) != opt_mapping.end(); +} + +pool_opts_t::opt_desc_t pool_opts_t::get_opt_desc(const std::string& name) { + opt_mapping_t::iterator i = opt_mapping.find(name); + assert(i != opt_mapping.end()); + return i->second; +} + +bool pool_opts_t::is_set(pool_opts_t::key_t key) const { + return opts.find(key) != opts.end(); +} + +const pool_opts_t::value_t& pool_opts_t::get(pool_opts_t::key_t key) const { + opts_t::const_iterator i = opts.find(key); + assert(i != opts.end()); + return i->second; +} + +bool pool_opts_t::unset(pool_opts_t::key_t key) { + return opts.erase(key) > 0; +} + +class pool_opts_dumper_t : public boost::static_visitor<> +{ +public: + pool_opts_dumper_t(const std::string& name_, Formatter* f_) : + name(name_.c_str()), f(f_) {} + + void operator()(std::string s) const { + f->dump_string(name, s); + } + void operator()(int i) const { + f->dump_int(name, i); + } + void operator()(double d) const { + f->dump_float(name, d); + } + +private: + const char* name; + Formatter* f; +}; + +void pool_opts_t::dump(const std::string& name, Formatter* f) const +{ + const opt_desc_t& desc = get_opt_desc(name); + opts_t::const_iterator i = opts.find(desc.key); + if (i == opts.end()) { + return; + } + boost::apply_visitor(pool_opts_dumper_t(name, f), i->second); +} + +void pool_opts_t::dump(Formatter* f) const +{ + for (opt_mapping_t::iterator i = opt_mapping.begin(); i != opt_mapping.end(); + i++) { + const std::string& name = i->first; + const opt_desc_t& desc = i->second; + opts_t::const_iterator j = opts.find(desc.key); + if (j == opts.end()) { + continue; + } + boost::apply_visitor(pool_opts_dumper_t(name, f), j->second); + } +} + +class pool_opts_encoder_t : public boost::static_visitor<> +{ +public: + pool_opts_encoder_t(bufferlist& bl_) : bl(bl_) {} + + void operator()(std::string s) const { + ::encode(static_cast(pool_opts_t::STR), bl); + ::encode(s, bl); + } + void operator()(int i) const { + ::encode(static_cast(pool_opts_t::INT), bl); + ::encode(i, bl); + } + void operator()(double d) const { + ::encode(static_cast(pool_opts_t::DOUBLE), bl); + ::encode(d, bl); + } + +private: + bufferlist& bl; +}; + +void pool_opts_t::encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + uint32_t n = static_cast(opts.size()); + ::encode(n, bl); + for (opts_t::const_iterator i = opts.begin(); i != opts.end(); ++i) { + ::encode(static_cast(i->first), bl); + boost::apply_visitor(pool_opts_encoder_t(bl), i->second); + } + ENCODE_FINISH(bl); +} + +void pool_opts_t::decode(bufferlist::iterator& bl) { + DECODE_START(1, bl); + __u32 n; + ::decode(n, bl); + opts.clear(); + while (n--) { + int32_t k, t; + ::decode(k, bl); + ::decode(t, bl); + if (t == STR) { + std::string s; + ::decode(s, bl); + opts[static_cast(k)] = s; + } else if (t == INT) { + int i; + ::decode(i, bl); + opts[static_cast(k)] = i; + } else if (t == DOUBLE) { + double d; + ::decode(d, bl); + opts[static_cast(k)] = d; + } else { + assert(!"invalid type"); + } + } + DECODE_FINISH(bl); +} + +ostream& operator<<(ostream& out, const pool_opts_t& opts) +{ + for (opt_mapping_t::iterator i = opt_mapping.begin(); i != opt_mapping.end(); + i++) { + const std::string& name = i->first; + const pool_opts_t::opt_desc_t& desc = i->second; + pool_opts_t::opts_t::const_iterator j = opts.opts.find(desc.key); + if (j == opts.opts.end()) { + continue; + } + out << " " << name << " " << j->second; + } + return out; +} + // -- pg_pool_t -- void pg_pool_t::dump(Formatter *f) const @@ -955,6 +1107,9 @@ void pg_pool_t::dump(Formatter *f) const f->dump_unsigned("stripe_width", get_stripe_width()); f->dump_unsigned("expected_num_objects", expected_num_objects); f->dump_bool("fast_read", fast_read); + f->open_object_section("options"); + opts.dump(f); + f->close_section(); // options } void pg_pool_t::convert_to_pg_shards(const vector &from, set* to) const { @@ -1264,7 +1419,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const return; } - ENCODE_START(23, 5, bl); + ENCODE_START(24, 5, bl); ::encode(type, bl); ::encode(size, bl); ::encode(crush_ruleset, bl); @@ -1312,12 +1467,13 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const ::encode(fast_read, bl); ::encode(hit_set_grade_decay_rate, bl); ::encode(hit_set_search_last_n, bl); + ::encode(opts, bl); ENCODE_FINISH(bl); } void pg_pool_t::decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN(23, 5, 5, bl); + DECODE_START_LEGACY_COMPAT_LEN(24, 5, 5, bl); ::decode(type, bl); ::decode(size, bl); ::decode(crush_ruleset, bl); @@ -1456,6 +1612,9 @@ void pg_pool_t::decode(bufferlist::iterator& bl) hit_set_grade_decay_rate = 0; hit_set_search_last_n = 1; } + if (struct_v >= 24) { + ::decode(opts, bl); + } DECODE_FINISH(bl); calc_pg_masks(); calc_grade_table(); @@ -1573,6 +1732,7 @@ ostream& operator<<(ostream& out, const pg_pool_t& p) out << " expected_num_objects " << p.expected_num_objects; if (p.fast_read) out << " fast_read " << p.fast_read; + out << p.opts; return out; } diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 86a1d98c864a..643fb48fbd0f 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "include/rados/rados_types.hpp" @@ -889,6 +890,77 @@ inline ostream& operator<<(ostream& out, const pool_snap_info_t& si) { } +/* + * pool_opts_t + * + * pool options. + */ + +class pool_opts_t { +public: + enum key_t { + }; + + enum type_t { + STR, + INT, + DOUBLE, + }; + + struct opt_desc_t { + key_t key; + type_t type; + + opt_desc_t(key_t k, type_t t) : key(k), type(t) {} + + bool operator==(const opt_desc_t& rhs) const { + return key == rhs.key && type == rhs.type; + } + }; + + typedef boost::variant value_t; + + static bool is_opt_name(const std::string& name); + static opt_desc_t get_opt_desc(const std::string& name); + + pool_opts_t() : opts() {} + + bool is_set(key_t key) const; + + template + void set(key_t key, const T &val) { + value_t value = val; + opts[key] = value; + } + + template + bool get(key_t key, T *val) const { + opts_t::const_iterator i = opts.find(key); + if (i == opts.end()) { + return false; + } + *val = boost::get(i->second); + return true; + } + + const value_t& get(key_t key) const; + + bool unset(key_t key); + + void dump(const std::string& name, Formatter *f) const; + + void dump(Formatter *f) const; + void encode(bufferlist &bl) const; + void decode(bufferlist::iterator &bl); + +private: + typedef std::map opts_t; + opts_t opts; + + friend ostream& operator<<(ostream& out, const pool_opts_t& opts); +}; +WRITE_CLASS_ENCODER(pool_opts_t) + /* * pg_pool */ @@ -1136,6 +1208,8 @@ public: ///< user does not specify any expected value bool fast_read; ///< whether turn on fast read on the pool or not + pool_opts_t opts; ///< options + private: vector grade_table; @@ -1183,7 +1257,8 @@ public: hit_set_search_last_n(0), stripe_width(0), expected_num_objects(0), - fast_read(false) + fast_read(false), + opts() { } void dump(Formatter *f) const; diff --git a/src/test/osd/types.cc b/src/test/osd/types.cc index b69a88a1c4e7..14f07c81073d 100644 --- a/src/test/osd/types.cc +++ b/src/test/osd/types.cc @@ -1388,6 +1388,11 @@ TEST(ghobject_t, cmp) { ASSERT_TRUE(cmp_bitwise(o, sep) > 0); } +TEST(pool_opts_t, invalid_opt) { + EXPECT_FALSE(pool_opts_t::is_opt_name("INVALID_OPT")); + EXPECT_THROW(pool_opts_t::get_opt_desc("INVALID_OPT"), FailedAssertion); +} + /* * Local Variables: * compile-command: "cd ../.. ;