From: Sage Weil Date: Thu, 21 May 2020 18:54:35 +0000 (-0500) Subject: cls/cas/cls_cas_internal: use DENC for refs_by_hash X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=f74e7bf9b6d75ff5f97c2105a2ebaa29a65739d8;p=ceph.git cls/cas/cls_cas_internal: use DENC for refs_by_hash In order to make the refs_t subtypes coexist with different encoding schemes, I had to move things into the .cc file (probably better anyway) and make them standalone classes (not subclasses). Signed-off-by: Sage Weil --- diff --git a/src/cls/CMakeLists.txt b/src/cls/CMakeLists.txt index 05db7f2908230..cb427482e92ff 100644 --- a/src/cls/CMakeLists.txt +++ b/src/cls/CMakeLists.txt @@ -251,9 +251,18 @@ set(cls_lua_client_srcs add_library(cls_lua_client STATIC ${cls_lua_client_srcs}) # cls_cas +set(cls_cas_client_srcs + cas/cls_cas_client.cc) +add_library(cls_cas_client STATIC ${cls_cas_client_srcs}) + +set(cls_cas_internal_srcs + cas/cls_cas_internal.cc) +add_library(cls_cas_internal STATIC ${cls_cas_internal_srcs}) + set(cls_cas_srcs cas/cls_cas.cc) add_library(cls_cas SHARED ${cls_cas_srcs}) +target_link_libraries(cls_cas cls_cas_internal) set_target_properties(cls_cas PROPERTIES VERSION "1.0.0" SOVERSION "1" @@ -261,9 +270,6 @@ set_target_properties(cls_cas PROPERTIES CXX_VISIBILITY_PRESET hidden) install(TARGETS cls_cas DESTINATION ${cls_dir}) -set(cls_cas_client_srcs - cas/cls_cas_client.cc) -add_library(cls_cas_client STATIC ${cls_cas_client_srcs}) #cls_queue set(cls_queue_srcs diff --git a/src/cls/cas/cls_cas_internal.cc b/src/cls/cas/cls_cas_internal.cc new file mode 100644 index 0000000000000..9c1deda468693 --- /dev/null +++ b/src/cls/cas/cls_cas_internal.cc @@ -0,0 +1,337 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "cls_cas_internal.h" + +struct refs_by_object : public chunk_obj_refcount::refs_t { + std::set by_object; + + uint8_t get_type() const { + return chunk_obj_refcount::TYPE_BY_OBJECT; + } + bool empty() const override { + return by_object.empty(); + } + uint64_t count() const override { + return by_object.size(); + } + bool get(const hobject_t& o) override { + if (by_object.count(o)) { + return false; + } + by_object.insert(o); + return true; + } + bool put(const hobject_t& o) override { + auto p = by_object.find(o); + if (p == by_object.end()) { + return false; + } + by_object.erase(p); + return true; + } + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(by_object, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& p) { + DECODE_START(1, p); + decode(by_object, p); + DECODE_FINISH(p); + } + void dump(Formatter *f) const override { + f->dump_string("type", "by_object"); + f->dump_unsigned("count", by_object.size()); + f->open_array_section("refs"); + for (auto& i : by_object) { + f->dump_object("ref", i); + } + f->close_section(); + } +}; +WRITE_CLASS_ENCODER(refs_by_object) + +struct refs_by_hash : public chunk_obj_refcount::refs_t { + uint64_t total = 0; + std::map,uint64_t> by_hash; + + refs_by_hash() {} + refs_by_hash(const refs_by_object *o) { + total = o->count(); + for (auto& i : o->by_object) { + by_hash[make_pair(i.pool, i.get_hash())]++; + } + } + + uint8_t get_type() const { + return chunk_obj_refcount::TYPE_BY_HASH; + } + bool empty() const override { + return by_hash.empty(); + } + uint64_t count() const override { + return total; + } + bool get(const hobject_t& o) override { + by_hash[make_pair(o.pool, o.get_hash())]++; + ++total; + return true; + } + bool put(const hobject_t& o) override { + auto p = by_hash.find(make_pair(o.pool, o.get_hash())); + if (p == by_hash.end()) { + return false; + } + if (--p->second == 0) { + by_hash.erase(p); + } + --total; + return true; + } + DENC(refs_by_hash, v, p) { + DENC_START(1, 1, p); + denc(v.total, p); + denc(v.by_hash, p); + DENC_FINISH(p); + } + void dump(Formatter *f) const override { + f->dump_string("type", "by_hash"); + f->dump_unsigned("count", total); + f->open_array_section("refs"); + for (auto& i : by_hash) { + f->open_object_section("hash"); + f->dump_int("pool", i.first.first); + f->dump_unsigned("hash", i.first.second); + f->dump_unsigned("count", i.second); + f->close_section(); + } + f->close_section(); + } +}; +WRITE_CLASS_DENC(refs_by_hash) + +struct refs_by_pool : public chunk_obj_refcount::refs_t { + uint64_t total = 0; + map by_pool; + + refs_by_pool() {} + refs_by_pool(const refs_by_hash *o) { + total = o->count(); + for (auto& i : o->by_hash) { + by_pool[i.first.first] += i.second; + } + } + + uint8_t get_type() const { + return chunk_obj_refcount::TYPE_BY_POOL; + } + bool empty() const override { + return by_pool.empty(); + } + uint64_t count() const override { + return total; + } + bool get(const hobject_t& o) override { + ++by_pool[o.pool]; + ++total; + return true; + } + bool put(const hobject_t& o) override { + auto p = by_pool.find(o.pool); + if (p == by_pool.end()) { + return false; + } + --p->second; + if (p->second == 0) { + by_pool.erase(p); + } + --total; + return true; + } + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(total, bl); + encode(by_pool, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& p) { + DECODE_START(1, p); + decode(total, p); + decode(by_pool, p); + DECODE_FINISH(p); + } + void dump(Formatter *f) const override { + f->dump_string("type", "by_pool"); + f->dump_unsigned("count", total); + f->open_array_section("pools"); + for (auto& i : by_pool) { + f->open_object_section("pool"); + f->dump_unsigned("pool_id", i.first); + f->dump_unsigned("count", i.second); + f->close_section(); + } + f->close_section(); + } +}; +WRITE_CLASS_ENCODER(refs_by_pool) + +struct refs_count : public chunk_obj_refcount::refs_t { + uint64_t total = 0; + + refs_count() {} + refs_count(const refs_t *old) { + total = old->count(); + } + + uint8_t get_type() const { + return chunk_obj_refcount::TYPE_COUNT; + } + bool empty() const override { + return total == 0; + } + uint64_t count() const override { + return total; + } + bool get(const hobject_t& o) override { + ++total; + return true; + } + bool put(const hobject_t& o) override { + if (!total) { + return false; + } + --total; + return true; + } + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(total, bl); + ENCODE_FINISH(bl); + } + void decode(bufferlist::const_iterator& p) { + DECODE_START(1, p); + decode(total, p); + DECODE_FINISH(p); + } + void dump(Formatter *f) const override { + f->dump_string("type", "count"); + f->dump_unsigned("count", total); + } +}; +WRITE_CLASS_ENCODER(refs_count) + + + +// + +void chunk_obj_refcount::clear() +{ + // default to most precise impl + r.reset(new refs_by_object); +} + + +void chunk_obj_refcount::encode(ceph::buffer::list& bl) const +{ + bufferlist t; + _encode_r(t); + _encode_final(bl, t); +} + +void chunk_obj_refcount::_encode_r(ceph::bufferlist& bl) const +{ + using ceph::encode; + switch (r->get_type()) { + case TYPE_BY_OBJECT: + encode(*(refs_by_object*)r.get(), bl); + break; + case TYPE_BY_HASH: + encode(*(refs_by_hash*)r.get(), bl); + break; + case TYPE_BY_POOL: + encode(*(refs_by_pool*)r.get(), bl); + break; + case TYPE_COUNT: + encode(*(refs_count*)r.get(), bl); + break; + default: + ceph_abort("unrecognized ref type"); + } +} + +void chunk_obj_refcount::dynamic_encode(ceph::buffer::list& bl, size_t max) +{ + bufferlist t; + while (true) { + _encode_r(t); + if (t.length() <= max) { + break; + } + // downgrade resolution + std::unique_ptr n; + switch (r->get_type()) { + case TYPE_BY_OBJECT: + n.reset(new refs_by_hash(static_cast(r.get()))); + break; + case TYPE_BY_HASH: + n.reset(new refs_by_pool(static_cast(r.get()))); + break; + case TYPE_BY_POOL: + n.reset(new refs_count(r.get())); + break; + } + r.swap(n); + t.clear(); + } + _encode_final(bl, t); +} + +void chunk_obj_refcount::_encode_final(bufferlist& bl, bufferlist& t) const +{ + ENCODE_START(1, 1, bl); + encode(r->get_type(), bl); + bl.claim_append(t); + ENCODE_FINISH(bl); +} + +void chunk_obj_refcount::decode(ceph::buffer::list::const_iterator& p) +{ + DECODE_START(1, p); + uint8_t t; + decode(t, p); + switch (t) { + case TYPE_BY_OBJECT: + { + auto n = new refs_by_object(); + decode(*n, p); + r.reset(n); + } + break; + case TYPE_BY_HASH: + { + auto n = new refs_by_hash(); + decode(*n, p); + r.reset(n); + } + break; + case TYPE_BY_POOL: + { + auto n = new refs_by_pool(); + decode(*n, p); + r.reset(n); + } + break; + case TYPE_COUNT: + { + auto n = new refs_count(); + decode(*n, p); + r.reset(n); + } + break; + default: + throw ceph::buffer::malformed_input( + "unrecognized chunk ref encoding type "s + stringify((int)t)); + } + DECODE_FINISH(p); +} diff --git a/src/cls/cas/cls_cas_internal.h b/src/cls/cas/cls_cas_internal.h index f0267f8605524..02cbcff560cea 100644 --- a/src/cls/cas/cls_cas_internal.h +++ b/src/cls/cas/cls_cas_internal.h @@ -7,6 +7,7 @@ #include "include/stringify.h" #include "common/Formatter.h" +#include "common/hobject.h" #define CHUNK_REFCOUNT_ATTR "chunk_refcount" @@ -26,242 +27,16 @@ struct chunk_obj_refcount { virtual uint64_t count() const = 0; virtual bool get(const hobject_t& o) = 0; virtual bool put(const hobject_t& o) = 0; - virtual void encode(bufferlist& bl) const = 0; - virtual void decode(bufferlist::const_iterator& p) = 0; virtual void dump(Formatter *f) const = 0; }; - struct refs_by_object : public refs_t { - std::set by_object; - - uint8_t get_type() const { - return TYPE_BY_OBJECT; - } - bool empty() const override { - return by_object.empty(); - } - uint64_t count() const override { - return by_object.size(); - } - bool get(const hobject_t& o) override { - if (by_object.count(o)) { - return false; - } - by_object.insert(o); - return true; - } - bool put(const hobject_t& o) override { - auto p = by_object.find(o); - if (p == by_object.end()) { - return false; - } - by_object.erase(p); - return true; - } - void encode(bufferlist& bl) const override { - ENCODE_START(1, 1, bl); - encode(by_object, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& p) override { - DECODE_START(1, p); - decode(by_object, p); - DECODE_FINISH(p); - } - void dump(Formatter *f) const override { - f->dump_string("type", "by_object"); - f->dump_unsigned("count", by_object.size()); - f->open_array_section("refs"); - for (auto& i : by_object) { - f->dump_object("ref", i); - } - f->close_section(); - } - }; - - struct refs_by_hash : public refs_t { - uint64_t total = 0; - std::map,uint64_t> by_hash; - - refs_by_hash() {} - refs_by_hash(const refs_by_object *o) { - total = o->count(); - for (auto& i : o->by_object) { - by_hash[make_pair(i.pool, i.get_hash())]++; - } - } - - uint8_t get_type() const { - return TYPE_BY_HASH; - } - bool empty() const override { - return by_hash.empty(); - } - uint64_t count() const override { - return total; - } - bool get(const hobject_t& o) override { - by_hash[make_pair(o.pool, o.get_hash())]++; - ++total; - return true; - } - bool put(const hobject_t& o) override { - auto p = by_hash.find(make_pair(o.pool, o.get_hash())); - if (p == by_hash.end()) { - return false; - } - if (--p->second == 0) { - by_hash.erase(p); - } - --total; - return true; - } - void encode(bufferlist& bl) const override { - ENCODE_START(1, 1, bl); - encode(total, bl); - encode(by_hash, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& p) override { - DECODE_START(1, p); - decode(total, p); - decode(by_hash, p); - DECODE_FINISH(p); - } - void dump(Formatter *f) const override { - f->dump_string("type", "by_hash"); - f->dump_unsigned("count", total); - f->open_array_section("refs"); - for (auto& i : by_hash) { - f->open_object_section("hash"); - f->dump_int("pool", i.first.first); - f->dump_unsigned("hash", i.first.second); - f->dump_unsigned("count", i.second); - f->close_section(); - } - f->close_section(); - } - }; - - struct refs_by_pool : public refs_t { - uint64_t total = 0; - map by_pool; - - refs_by_pool() {} - refs_by_pool(const refs_by_hash *o) { - total = o->count(); - for (auto& i : o->by_hash) { - by_pool[i.first.first] += i.second; - } - } - - uint8_t get_type() const { - return TYPE_BY_POOL; - } - bool empty() const override { - return by_pool.empty(); - } - uint64_t count() const override { - return total; - } - bool get(const hobject_t& o) override { - ++by_pool[o.pool]; - ++total; - return true; - } - bool put(const hobject_t& o) override { - auto p = by_pool.find(o.pool); - if (p == by_pool.end()) { - return false; - } - --p->second; - if (p->second == 0) { - by_pool.erase(p); - } - --total; - return true; - } - void encode(bufferlist& bl) const override { - ENCODE_START(1, 1, bl); - encode(total, bl); - encode(by_pool, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& p) override { - DECODE_START(1, p); - decode(total, p); - decode(by_pool, p); - DECODE_FINISH(p); - } - void dump(Formatter *f) const override { - f->dump_string("type", "by_pool"); - f->dump_unsigned("count", total); - f->open_array_section("pools"); - for (auto& i : by_pool) { - f->open_object_section("pool"); - f->dump_unsigned("pool_id", i.first); - f->dump_unsigned("count", i.second); - f->close_section(); - } - f->close_section(); - } - }; - - struct refs_count : public refs_t { - uint64_t total = 0; - - refs_count() {} - refs_count(const refs_t *old) { - total = old->count(); - } - - uint8_t get_type() const { - return TYPE_COUNT; - } - bool empty() const override { - return total == 0; - } - uint64_t count() const override { - return total; - } - bool get(const hobject_t& o) override { - ++total; - return true; - } - bool put(const hobject_t& o) override { - if (!total) { - return false; - } - --total; - return true; - } - void encode(bufferlist& bl) const override { - ENCODE_START(1, 1, bl); - encode(total, bl); - ENCODE_FINISH(bl); - } - void decode(bufferlist::const_iterator& p) override { - DECODE_START(1, p); - decode(total, p); - DECODE_FINISH(p); - } - void dump(Formatter *f) const override { - f->dump_string("type", "count"); - f->dump_unsigned("count", total); - } - }; - - std::unique_ptr r; chunk_obj_refcount() { clear(); } - void clear() { - // default to most precise impl - r.reset(new refs_by_object); - } + void clear(); int get_type() const { return r->get_type(); @@ -286,69 +61,11 @@ struct chunk_obj_refcount { return ret; } - void encode(ceph::buffer::list& bl) const { - bufferlist t; - r->encode(t); - _encode(bl, t); - } - - void dynamic_encode(ceph::buffer::list& bl, size_t max = 1024) { - bufferlist t; - while (true) { - r->encode(t); - if (t.length() <= max) { - break; - } - // downgrade resolution - std::unique_ptr n; - switch (r->get_type()) { - case TYPE_BY_OBJECT: - n.reset(new refs_by_hash(static_cast(r.get()))); - break; - case TYPE_BY_HASH: - n.reset(new refs_by_pool(static_cast(r.get()))); - break; - case TYPE_BY_POOL: - n.reset(new refs_count(r.get())); - break; - } - r.swap(n); - t.clear(); - } - _encode(bl, t); - } - - void _encode(bufferlist& bl, bufferlist& t) const { - ENCODE_START(1, 1, bl); - encode(r->get_type(), bl); - bl.claim_append(t); - ENCODE_FINISH(bl); - } - - void decode(ceph::buffer::list::const_iterator& p) { - DECODE_START(1, p); - uint8_t t; - decode(t, p); - switch (t) { - case TYPE_BY_OBJECT: - r.reset(new refs_by_object()); - break; - case TYPE_BY_HASH: - r.reset(new refs_by_hash()); - break; - case TYPE_BY_POOL: - r.reset(new refs_by_pool()); - break; - case TYPE_COUNT: - r.reset(new refs_count()); - break; - default: - throw ceph::buffer::malformed_input( - "unrecognized chunk ref encoding type "s + stringify((int)t)); - } - r->decode(p); - DECODE_FINISH(p); - } + void _encode_r(bufferlist& bl) const; + void _encode_final(bufferlist& bl, bufferlist& t) const; + void dynamic_encode(ceph::buffer::list& bl, size_t max = 1024); + void encode(ceph::buffer::list& bl) const; + void decode(ceph::buffer::list::const_iterator& p); void dump(Formatter *f) const { r->dump(f); diff --git a/src/test/cls_cas/CMakeLists.txt b/src/test/cls_cas/CMakeLists.txt index 83426bc6068c7..16bff8b3b68f6 100644 --- a/src/test/cls_cas/CMakeLists.txt +++ b/src/test/cls_cas/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(ceph_test_cls_cas target_link_libraries(ceph_test_cls_cas librados cls_cas_client + cls_cas_internal global radostest-cxx ${UNITTEST_LIBS} diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index f460ce1ae2d18..2f09329b48e75 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -118,7 +118,11 @@ install(TARGETS ceph-authtool DESTINATION bin) if(WITH_TESTS) set(ceph_dedup_tool_srcs ceph_dedup_tool.cc) add_executable(ceph-dedup-tool ${ceph_dedup_tool_srcs}) -target_link_libraries(ceph-dedup-tool librados global cls_cas_client) +target_link_libraries(ceph-dedup-tool + librados + global + cls_cas_client + cls_cas_internal) install(TARGETS ceph-dedup-tool DESTINATION bin) endif(WITH_TESTS) diff --git a/src/tools/ceph-dencoder/CMakeLists.txt b/src/tools/ceph-dencoder/CMakeLists.txt index 5f6b426cae6c9..4a7b452f71d73 100644 --- a/src/tools/ceph-dencoder/CMakeLists.txt +++ b/src/tools/ceph-dencoder/CMakeLists.txt @@ -71,6 +71,8 @@ target_link_libraries(ceph-dencoder cls_user_client cls_journal_client cls_timeindex_client + cls_cas_internal + cls_cas_client ${EXTRALIBS} ${CMAKE_DL_LIBS}) install(TARGETS ceph-dencoder DESTINATION bin)