#include "include/buffer_fwd.h"
#include "os/ObjectStore.h"
#include "test/objectstore/ObjectStoreImitator.h"
+#include <fmt/core.h>
#include <gtest/gtest.h>
#include <iostream>
void FragmentationSimulator::init(const std::string &alloc_type, uint64_t size,
uint64_t min_alloc_size) {
+ std::cout << std::endl;
std::cout << "Initializing ObjectStoreImitator" << std::endl;
os = new ObjectStoreImitator(g_ceph_context, "", min_alloc_size);
std::string name() override { return "SimpleCW"; }
int generate_txns(ObjectStore::CollectionHandle &ch,
ObjectStoreImitator *os) override {
- hobject_t h1;
- h1.oid = "obj_1";
- h1.set_hash(1);
- h1.pool = 1;
- auto oid = ghobject_t(h1);
-
- ObjectStore::Transaction t1;
- t1.create(ch->get_cid(), oid);
- os->queue_transaction(ch, std::move(t1));
-
- ObjectStore::Transaction t2;
- t2.write(ch->get_cid(), oid, 0, _1Mb, make_bl(_1Mb, 'c'));
- os->queue_transaction(ch, std::move(t2));
+ std::vector<ghobject_t> objs;
+ for (unsigned i{0}; i < 100; ++i) {
+ hobject_t h;
+ h.oid = fmt::format("obj_{}", i);
+ h.set_hash(1);
+ h.pool = 1;
+ objs.emplace_back(h);
+ }
+
+ std::vector<ObjectStore::Transaction> tls;
+ for (unsigned i{0}; i < 100; ++i) {
+ ObjectStore::Transaction t1;
+ t1.create(ch->get_cid(), objs[i]);
+ tls.emplace_back(std::move(t1));
+
+ ObjectStore::Transaction t2;
+ t2.write(ch->get_cid(), objs[i], 0, _1Mb, make_bl(_1Mb, 'c'));
+ tls.emplace_back(std::move(t2));
+ }
+
+ os->queue_transactions(ch, tls);
+
+ // reapply
+ os->queue_transactions(ch, tls);
+ tls.clear();
+
+ // Overwrite on object
+ for (unsigned i{0}; i < 100; ++i) {
+ ObjectStore::Transaction t;
+ t.write(ch->get_cid(), objs[i], _1Kb * i, _1Mb * 3,
+ make_bl(_1Mb * 3, 'x'));
+ tls.emplace_back(std::move(t));
+ }
+
+ os->queue_transactions(ch, tls);
+ tls.clear();
+
+ for (unsigned i{0}; i < 50; ++i) {
+ ObjectStore::Transaction t1, t2;
+ t1.clone(ch->get_cid(), objs[i], objs[i + 50]);
+ tls.emplace_back(std::move(t1));
+
+ t2.clone(ch->get_cid(), objs[i + 50], objs[i]);
+ tls.emplace_back(std::move(t2));
+ }
+
+ os->queue_transactions(ch, tls);
return 0;
}
};
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
common_init_finish(FragmentationSimulator::cct->get());
+ FragmentationSimulator::cct->_conf->bluestore_clone_cow = false;
+
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#include "test/objectstore/ObjectStoreImitator.h"
#include "common/errno.h"
#include "include/ceph_assert.h"
+#include "include/intarith.h"
#define dout_context cct
#define OBJECT_MAX_SIZE 0xffffffff // 32 bits
std::cout << std::hex
<< "Fragmentation score: " << alloc->get_fragmentation_score()
<< " , fragmentation: " << alloc->get_fragmentation()
- << ", allocator name " << alloc->get_name() << ", allocator type "
- << alloc->get_type() << ", capacity 0x" << alloc->get_capacity()
- << ", block size 0x" << alloc->get_block_size() << ", free 0x"
- << alloc->get_free() << std::dec << std::endl;
+ << ", allocator type " << alloc->get_type() << ", capacity 0x"
+ << alloc->get_capacity() << ", block size 0x"
+ << alloc->get_block_size() << ", free 0x" << alloc->get_free()
+ << std::dec << std::endl;
}
// ------- Transactions -------
bufferlist &bl) {
// No compression for now
- uint64_t need = bl.length();
+ uint64_t need = p2roundup(static_cast<uint64_t>(bl.length()), min_alloc_size);
PExtentVector prealloc;
void punch_hole(uint64_t offset, uint64_t length,
PExtentVector &old_extents) {
- if (offset > size || length == 0)
+ if (offset >= size || length == 0)
return;
+ if (offset + length >= size) {
+ length = size - offset;
+ }
+
uint64_t l_offset{0}, punched_length{0};
PExtentVector to_be_punched, remains;
for (auto e : extents) {
// Found where we need to punch
if (l_offset >= offset) {
- if (e.length + punched_length >= length) {
+ // We only punched a portion of the extent
+ if (e.length + punched_length > length) {
uint64_t left = e.length + punched_length - length;
e.length = length - punched_length;
remains.emplace_back(e.offset + e.length, left);