]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd_types: ObjectModDesc
authorSamuel Just <sam.just@inktank.com>
Wed, 4 Dec 2013 00:22:53 +0000 (16:22 -0800)
committerSamuel Just <sam.just@inktank.com>
Wed, 22 Jan 2014 22:39:15 +0000 (14:39 -0800)
Contains information needed to roll back a pg_log_entry_t.

Signed-off-by: Samuel Just <sam.just@inktank.com>
src/include/encoding.h
src/osd/osd_types.cc
src/osd/osd_types.h

index 51af378c56610cad8e93cf37efbda7968f12013a..07c529f4f62851168c13ddd5a0f568be13115c28 100644 (file)
@@ -286,6 +286,7 @@ inline void decode(T &o, bufferlist& bl)
 #include <deque>
 #include <vector>
 #include <string>
+#include <boost/optional.hpp>
 
 #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<typename T>
+inline void encode(const boost::optional<T> &p, bufferlist &bl)
+{
+  __u8 present = static_cast<bool>(p);
+  ::encode(present, bl);
+  if (p)
+    ::encode(p.get(), bl);
+}
+
+template<typename T>
+inline void decode(boost::optional<T> &p, bufferlist::iterator &bp)
+{
+  __u8 present;
+  ::decode(present, bp);
+  if (present) {
+    T t;
+    p = t;
+    ::decode(p.get(), bp);
+  }
+}
+
 // pair
 template<class A, class B>
 inline void encode(const std::pair<A,B> &p, bufferlist &bl)
index 855b5d85c598f61b859e02b1a412ae2c1c74b807..b668eb8e35b4ab09b3ff18962fe58e163d81dd04 100644 (file)
@@ -2111,6 +2111,145 @@ void pg_query_t::generate_test_instances(list<pg_query_t*>& 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<string, boost::optional<bufferlist> > 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<snapid_t> 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<string, boost::optional<bufferlist> > &attrs) {
+    f->open_object_section("op");
+    f->dump_string("code", "SETATTRS");
+    f->open_array_section("attrs");
+    for (map<string, boost::optional<bufferlist> >::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<snapid_t> &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<ObjectModDesc*>& o)
+{
+  map<string, boost::optional<bufferlist> > 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 --
 
index cf9b9b8854afa39d5082991fd0eec717754dd49b..d537c88a39f894167b28e9c78ecc4720d9c4e318 100644 (file)
@@ -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<string, boost::optional<bufferlist> > &attrs) {}
+    virtual void rmobject(version_t old_version) {}
+    virtual void create() {}
+    virtual void update_snaps(set<snapid_t> &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<string, boost::optional<bufferlist> > &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<snapid_t> &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<ObjectModDesc*>& o);
+};
+WRITE_CLASS_ENCODER(ObjectModDesc)
+
 
 /**
  * pg_log_entry_t - single entry/event in pg log