case DSOP_COLL_CREATE:
ok = do_coll_create(gen);
break;
+ case DSOP_MERGE_DELETE:
+ ok = do_move_ranges_delete_srcobj(gen);
+ break;
+
default:
assert(0 == "bad op");
}
return true;
}
+bool DeterministicOpSequence::do_move_ranges_delete_srcobj(rngen_t& gen)
+{
+ coll_t coll;
+ hobject_t orig_obj, new_obj;
+ if (!_prepare_clone(gen, coll, orig_obj, new_obj)) {
+ return false;
+ }
+
+ /* Whenever we have to make a merge_delete() operation, just write to the
+ * object first, so we know we have something to move in the said range.
+ */
+
+ boost::uniform_int<> write_size_rng(100, (2 << 19));
+ size_t size = (size_t) write_size_rng(gen);
+ bufferlist bl;
+ _gen_random(gen, size, bl);
+
+ boost::uniform_int<> move_len(1, bl.length());
+ size = (size_t) move_len(gen);
+
+ vector<boost::tuple<uint64_t, uint64_t, uint64_t>> move_info = { boost::make_tuple(0, 0, size)};
+
+ dout(0) << "do_move_ranges_delete_srcobj " << coll.to_str() << "/" << orig_obj.oid.name
+ << " (0~" << size << ")"
+ << " => " << coll.to_str() << "/" << new_obj.oid.name
+ << " (0)" << dendl;
+ _do_write_and_merge_delete(coll, orig_obj, new_obj, move_info, bl);
+ return true;
+}
+
+
bool DeterministicOpSequence::_prepare_colls(rngen_t& gen,
coll_entry_t* &orig_coll, coll_entry_t* &new_coll)
{
m_store->apply_transaction(&m_osr, std::move(t));
}
+void DeterministicOpSequence::_do_write_and_merge_delete(coll_t coll,
+ hobject_t& orig_obj,
+ hobject_t& new_obj,
+ vector<boost::tuple<uint64_t, uint64_t, uint64_t>> move_info,
+ bufferlist& bl)
+{
+ ObjectStore::Transaction t;
+
+ note_txn(&t);
+ for (unsigned i = 0; i < move_info.size(); ++i) {
+ uint64_t srcoff = move_info[i].get<0>();
+ t.write(coll, ghobject_t(orig_obj), srcoff, bl.length(), bl);
+ }
+ t.move_ranges_destroy_src(coll, ghobject_t(orig_obj), ghobject_t(new_obj), move_info);
+ m_store->apply_transaction(&m_osr, std::move(t));
+}
+
void DeterministicOpSequence::_do_coll_move(coll_t orig_coll, coll_t new_coll,
hobject_t& obj)
{
DSOP_CLONE = 2,
DSOP_CLONE_RANGE = 3,
DSOP_OBJ_REMOVE = 4,
- DSOP_COLL_MOVE = 6,
- DSOP_SET_ATTRS = 7,
- DSOP_COLL_CREATE = 8,
+ DSOP_COLL_MOVE = 5,
+ DSOP_SET_ATTRS = 6,
+ DSOP_COLL_CREATE = 7,
+ DSOP_MERGE_DELETE = 8,
DSOP_FIRST = DSOP_TOUCH,
- DSOP_LAST = DSOP_COLL_CREATE,
+ DSOP_LAST = DSOP_MERGE_DELETE,
};
int32_t txn;
bool do_coll_move(rngen_t& gen);
bool do_set_attrs(rngen_t& gen);
bool do_coll_create(rngen_t& gen);
+ bool do_move_ranges_delete_srcobj(rngen_t& gen);
virtual void _do_touch(coll_t coll, hobject_t& obj);
virtual void _do_remove(coll_t coll, hobject_t& obj);
virtual void _do_write_and_clone_range(coll_t coll, hobject_t& orig_obj,
hobject_t& new_obj, uint64_t srcoff, uint64_t srclen,
uint64_t dstoff, bufferlist& bl);
+ virtual void _do_write_and_merge_delete(coll_t coll, hobject_t& orig_obj,
+ hobject_t& new_obj, vector<boost::tuple<uint64_t, uint64_t, uint64_t>> move_info,
+ bufferlist& bl);
virtual void _do_coll_move(coll_t orig_coll, coll_t new_coll, hobject_t& obj);
virtual void _do_coll_create(coll_t cid, uint32_t pg_num, uint64_t num_objs);
}
}
+TEST_P(StoreTest, SimpleMoveRangeDelSrcTest) {
+ ObjectStore::Sequencer osr("test");
+ int r;
+ coll_t cid;
+ {
+ ObjectStore::Transaction t;
+ t.create_collection(cid, 0);
+ cerr << "Creating collection " << cid << std::endl;
+ r = apply_transaction(store, &osr, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+
+ ghobject_t hoid(hobject_t(sobject_t("Object 1", CEPH_NOSNAP)));
+ hoid.hobj.pool = -1;
+ ghobject_t hoid2(hobject_t(sobject_t("Object 2", CEPH_NOSNAP)));
+ hoid2.hobj.pool = -1;
+
+ bufferlist small, newdata;
+ small.append("small");
+ {
+ ObjectStore::Transaction t;
+ t.write(cid, hoid2, 0, 5, small);
+ cerr << "Creating object2 and write bl " << hoid << std::endl;
+ r = apply_transaction(store, &osr, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+ {
+ ObjectStore::Transaction t;
+ t.write(cid, hoid2, 10, 5, small);
+ cerr << "Writing object2 again " << hoid << std::endl;
+ r = apply_transaction(store, &osr, std::move(t));
+ ASSERT_EQ(r, 0);
+
+ }
+ {
+ vector<boost::tuple<uint64_t, uint64_t, uint64_t>> move_info = { boost::make_tuple(0, 0, 5), boost::make_tuple(10, 10, 5) };
+
+ ObjectStore::Transaction t;
+ t.move_ranges_destroy_src(cid, hoid2, hoid, move_info);
+ cerr << "move temp object" << std::endl;
+ r = apply_transaction(store, &osr, std::move(t));
+ ASSERT_EQ(r, 0);
+
+ r = store->read(cid, hoid, 0, 5, newdata);
+ ASSERT_EQ(r, 5);
+ ASSERT_TRUE(newdata.contents_equal(small));
+
+ r = store->read(cid, hoid, 10, 5, newdata);
+ ASSERT_EQ(r, 5);
+ ASSERT_TRUE(newdata.contents_equal(small));
+
+ }
+ {
+ ObjectStore::Transaction t;
+ t.remove(cid, hoid);
+ t.remove_collection(cid);
+ cerr << "Cleaning" << std::endl;
+ r = apply_transaction(store, &osr, std::move(t));
+ ASSERT_EQ(r, 0);
+ }
+}
+
TEST_P(StoreTest, OmapSimple) {
ObjectStore::Sequencer osr("test");
int r;
#include <gtest/gtest.h>
#include "common/Clock.h"
#include "include/utime.h"
+#include <boost/tuple/tuple.hpp>
TEST(Transaction, MoveConstruct)
{
return a;
}
+TEST(Transaction, MoveRangesDelSrcObj)
+{
+ auto t = ObjectStore::Transaction{};
+ t.set_use_tbl(false);
+ t.nop();
+
+ coll_t c(spg_t(pg_t(1,2), shard_id_t::NO_SHARD));
+
+ ghobject_t o1(hobject_t("obj", "", 123, 456, -1, ""));
+ ghobject_t o2(hobject_t("obj2", "", 123, 456, -1, ""));
+ vector<boost::tuple<uint64_t, uint64_t, uint64_t>> move_info = { boost::make_tuple(1, 1, 5), boost::make_tuple(10, 10, 5) };
+
+ t.touch(c, o1);
+ bufferlist bl;
+ bl.append("some data");
+ t.write(c, o1, 1, bl.length(), bl);
+ t.write(c, o1, 10, bl.length(), bl);
+
+ t.clone(c, o1, o2);
+ bl.append("some other data");
+ t.write(c, o2, 1, bl.length(), bl);
+
+ t.move_ranges_destroy_src(c, o1, o2, move_info);
+
+}
+
TEST(Transaction, GetNumBytes)
{
auto a = ObjectStore::Transaction{};