From: Samuel Just Date: Wed, 4 Dec 2013 00:22:53 +0000 (-0800) Subject: osd_types: ObjectModDesc X-Git-Tag: v0.78~286^2~31 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a7a6a2f153d0f1728cb41c68e023022b5f306ab9;p=ceph.git osd_types: ObjectModDesc Contains information needed to roll back a pg_log_entry_t. Signed-off-by: Samuel Just --- diff --git a/src/include/encoding.h b/src/include/encoding.h index 51af378c5661..07c529f4f628 100644 --- a/src/include/encoding.h +++ b/src/include/encoding.h @@ -286,6 +286,7 @@ inline void decode(T &o, bufferlist& bl) #include #include #include +#include #ifndef _BACKWARD_BACKWARD_WARNING_H #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_* @@ -295,6 +296,28 @@ inline void decode(T &o, bufferlist& bl) #include "triple.h" +// boost optional +template +inline void encode(const boost::optional &p, bufferlist &bl) +{ + __u8 present = static_cast(p); + ::encode(present, bl); + if (p) + ::encode(p.get(), bl); +} + +template +inline void decode(boost::optional &p, bufferlist::iterator &bp) +{ + __u8 present; + ::decode(present, bp); + if (present) { + T t; + p = t; + ::decode(p.get(), bp); + } +} + // pair template inline void encode(const std::pair &p, bufferlist &bl) diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index 855b5d85c598..b668eb8e35b4 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -2111,6 +2111,145 @@ void pg_query_t::generate_test_instances(list& o) o.push_back(new pg_query_t(pg_query_t::FULLLOG, *h.back(), 5)); } +// -- ObjectModDesc -- +void ObjectModDesc::visit(Visitor *visitor) const +{ + bufferlist::iterator bp = bl.begin(); + try { + while (!bp.end()) { + DECODE_START(1, bp); + uint8_t code; + ::decode(code, bp); + switch (code) { + case APPEND: { + uint64_t size; + ::decode(size, bp); + visitor->append(size); + break; + } + case SETATTRS: { + map > attrs; + ::decode(attrs, bp); + visitor->setattrs(attrs); + break; + } + case DELETE: { + version_t old_version; + ::decode(old_version, bp); + visitor->rmobject(old_version); + break; + } + case CREATE: { + visitor->create(); + break; + } + case UPDATE_SNAPS: { + set snaps; + ::decode(snaps, bp); + visitor->update_snaps(snaps); + break; + } + default: + assert(0 == "Invalid rollback code"); + } + DECODE_FINISH(bp); + } + } catch (...) { + assert(0 == "Invalid encoding"); + } +} + +struct DumpVisitor : public ObjectModDesc::Visitor { + Formatter *f; + DumpVisitor(Formatter *f) : f(f) {} + void append(uint64_t old_size) { + f->open_object_section("op"); + f->dump_string("code", "APPEND"); + f->dump_unsigned("old_size", old_size); + f->close_section(); + } + void setattrs(map > &attrs) { + f->open_object_section("op"); + f->dump_string("code", "SETATTRS"); + f->open_array_section("attrs"); + for (map >::iterator i = attrs.begin(); + i != attrs.end(); + ++i) { + f->dump_string("attr_name", i->first); + } + f->close_section(); + f->close_section(); + } + void rmobject(version_t old_version) { + f->open_object_section("op"); + f->dump_string("code", "RMOBJECT"); + f->dump_unsigned("old_version", old_version); + f->close_section(); + } + void create() { + f->open_object_section("op"); + f->dump_string("code", "CREATE"); + f->close_section(); + } + void update_snaps(set &snaps) { + f->open_object_section("op"); + f->dump_string("code", "UPDATE_SNAPS"); + f->dump_stream("snaps") << snaps; + f->close_section(); + } +}; + +void ObjectModDesc::dump(Formatter *f) const +{ + f->open_object_section("object_mod_desc"); + f->dump_stream("can_local_rollback") << can_local_rollback; + f->dump_stream("stashed") << stashed; + { + f->open_array_section("ops"); + DumpVisitor vis(f); + visit(&vis); + f->close_section(); + } + f->close_section(); +} + +void ObjectModDesc::generate_test_instances(list& o) +{ + map > attrs; + attrs[OI_ATTR]; + attrs[SS_ATTR]; + attrs["asdf"]; + o.push_back(new ObjectModDesc()); + o.back()->append(100); + o.back()->setattrs(attrs); + o.push_back(new ObjectModDesc()); + o.back()->rmobject(1001); + o.push_back(new ObjectModDesc()); + o.back()->create(); + o.back()->setattrs(attrs); + o.push_back(new ObjectModDesc()); + o.back()->create(); + o.back()->setattrs(attrs); + o.back()->mark_unrollbackable(); + o.back()->append(1000); +} + +void ObjectModDesc::encode(bufferlist &_bl) const +{ + ENCODE_START(1, 1, _bl); + ::encode(can_local_rollback, _bl); + ::encode(stashed, _bl); + ::encode(bl, _bl); + ENCODE_FINISH(_bl); +} +void ObjectModDesc::decode(bufferlist::iterator &_bl) +{ + DECODE_START(1, _bl); + ::decode(can_local_rollback, _bl); + ::decode(stashed, _bl); + ::decode(bl, _bl); + DECODE_FINISH(_bl); +} // -- pg_log_entry_t -- diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index cf9b9b8854af..d537c88a39f8 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -1582,6 +1582,100 @@ inline ostream& operator<<(ostream& out, const pg_query_t& q) { return out; } +class PGBackend; +class ObjectModDesc { + bool can_local_rollback; + bool stashed; +public: + class Visitor { + public: + virtual void append(uint64_t old_offset) {} + virtual void setattrs(map > &attrs) {} + virtual void rmobject(version_t old_version) {} + virtual void create() {} + virtual void update_snaps(set &old_snaps) {} + virtual ~Visitor() {} + }; + void visit(Visitor *visitor) const; + mutable bufferlist bl; + enum ModID { + APPEND = 1, + SETATTRS = 2, + DELETE = 3, + CREATE = 4, + UPDATE_SNAPS = 5 + }; + ObjectModDesc() : can_local_rollback(true), stashed(false) {} + void claim(ObjectModDesc &other) { + bl.clear(); + bl.claim(other.bl); + can_local_rollback = other.can_local_rollback; + stashed = other.stashed; + } + void append_id(ModID id) { + uint8_t _id(id); + ::encode(_id, bl); + } + void append(uint64_t old_size) { + if (!can_local_rollback || stashed) + return; + ENCODE_START(1, 1, bl); + append_id(APPEND); + ::encode(old_size, bl); + ENCODE_FINISH(bl); + } + void setattrs(map > &old_attrs) { + if (!can_local_rollback || stashed) + return; + ENCODE_START(1, 1, bl); + append_id(SETATTRS); + ::encode(old_attrs, bl); + ENCODE_FINISH(bl); + } + bool rmobject(version_t deletion_version) { + if (!can_local_rollback || stashed) + return false; + ENCODE_START(1, 1, bl); + append_id(DELETE); + ::encode(deletion_version, bl); + ENCODE_FINISH(bl); + stashed = true; + return true; + } + void create() { + if (!can_local_rollback || stashed) + return; + ENCODE_START(1, 1, bl); + append_id(CREATE); + ENCODE_FINISH(bl); + } + void update_snaps(set &old_snaps) { + if (!can_local_rollback || stashed) + return; + ENCODE_START(1, 1, bl); + append_id(UPDATE_SNAPS); + ::encode(old_snaps, bl); + ENCODE_FINISH(bl); + } + + // cannot be rolled back + void mark_unrollbackable() { + can_local_rollback = false; + bl.clear(); + } + bool can_rollback() const { + return can_local_rollback; + } + bool empty() const { + return can_local_rollback && (bl.length() == 0); + } + void encode(bufferlist &bl) const; + void decode(bufferlist::iterator &bl); + void dump(Formatter *f) const; + static void generate_test_instances(list& o); +}; +WRITE_CLASS_ENCODER(ObjectModDesc) + /** * pg_log_entry_t - single entry/event in pg log