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 --
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