#define dout_context cct
#define OBJECT_MAX_SIZE 0xffffffff // 32 bits
+// ---------- Object -----------
+
+void ObjectStoreImitator::Object::punch_hole(uint64_t offset, uint64_t length,
+ uint64_t min_alloc_size,
+ PExtentVector &old_extents) {
+ if (extent_map.empty())
+ return;
+
+ PExtentVector to_be_punched;
+ std::vector<uint64_t> deleted_keys;
+ uint64_t end = offset + length;
+
+ uint64_t re_add_key{0};
+ bluestore_pextent_t re_add;
+
+ // std::cout << "current extents:\n";
+ // for (auto &[l_off, e] : extent_map) {
+ // std::cout << "l_off " << l_off << ", off " << e.offset << ", len "
+ // << e.length << std::endl;
+ // }
+
+ // std::cout << "wants to punch: off " << offset << ", len " << length
+ // << std::endl;
+
+ auto it = extent_map.lower_bound(offset);
+ if ((it == extent_map.end() || it->first > offset) &&
+ it != extent_map.begin()) {
+ it = std::prev(it);
+
+ // diff between where we need to punch and current position
+ auto diff = offset - it->first;
+ // std::cout << "diff " << diff << " , p_off " << it->first <<
+ // std::endl;
+
+ // offset will be inside this extent
+ // otherwise skip over this extent and assume 'offset' has been passed
+ if (diff < it->second.length) {
+ // the hole is bigger than the remaining of the extent
+ if (end > it->first + it->second.length) {
+ to_be_punched.emplace_back(it->second.offset + diff,
+ it->second.length - diff);
+ } else { // else the hole is entirely in this extent
+ to_be_punched.emplace_back(it->second.offset + diff, length);
+
+ re_add_key = end;
+ re_add.offset = it->second.offset + diff + length;
+ re_add.length = it->second.length - diff - length;
+
+ // std::cout << "re_add: off " << re_add.offset << ", len "
+ // << re_add.length << std::endl;
+ }
+
+ // Modify the remaining extent's length
+ it->second.length = diff;
+ }
+
+ it++;
+ }
+
+ // this loop is only valid when 'it' is in the hole
+ while (it != extent_map.end() && it->first < end) {
+ if (it->first + it->second.length > end) { // last extent to punched
+ uint64_t remaining = it->first + it->second.length - end;
+ uint64_t punched = it->second.length - remaining;
+
+ to_be_punched.emplace_back(it->second.offset, punched);
+ deleted_keys.push_back(it->first);
+
+ re_add.offset = it->second.offset + punched;
+ re_add.length = remaining;
+ re_add_key = it->first + punched;
+
+ it++;
+ break;
+ }
+
+ deleted_keys.push_back(it->first);
+ to_be_punched.push_back(it->second);
+ it++;
+ }
+
+ for (auto k : deleted_keys) {
+ extent_map.erase(k);
+ }
+
+ if (re_add.length > 0) {
+ extent_map[re_add_key] = re_add;
+ }
+
+ old_extents = to_be_punched;
+ // std::cout << "to be deleted\n";
+ // for (auto e : to_be_punched) {
+ // std::cout << "off " << e.offset << ", len " << e.length << std::endl;
+ // }
+}
+
+void ObjectStoreImitator::Object::append(PExtentVector &ext, uint64_t offset) {
+ for (auto &e : ext) {
+ ceph_assert(e.length > 0);
+ // std::cout << "adding off " << offset << ", len " << e.length
+ // << std::endl;
+ extent_map[offset] = e;
+ offset += e.length;
+ }
+}
+
+void ObjectStoreImitator::Object::verify_extents() {
+ // std::cout << "verifying extents:\n";
+ for (auto &[l_off, ext] : extent_map) {
+ // std::cout << l_off << " " << ext.offset << " " << ext.length
+ // << std::endl;
+ ceph_assert(ext.is_valid());
+ ceph_assert(ext.length > 0);
+ }
+}
+
+uint64_t ObjectStoreImitator::Object::ext_length() {
+ uint64_t ret{0};
+ for (auto &[_, ext] : extent_map) {
+ ret += ext.length;
+ }
+ return ret;
+}
+
+// ---------- ObjectStoreImitator ----------
+
void ObjectStoreImitator::init_alloc(const std::string &alloc_type,
uint64_t size) {
alloc.reset(Allocator::create(cct, alloc_type, size, min_alloc_size));
double coll_total{0};
for (auto &[id, obj] : coll_ref->objects) {
double frag_score{1};
- unsigned i{1};
- uint64_t ext_size = obj->ext_length();
+ unsigned i{2};
+ uint64_t ext_size = 0;
+ PExtentVector extents;
for (auto &[_, ext] : obj->extent_map) {
+ extents.push_back(ext);
+ ext_size += ext.length;
+ }
+
+ std::sort(extents.begin(), extents.end(),
+ [](bluestore_pextent_t &a, bluestore_pextent_t &b) {
+ return a.length > b.length;
+ });
+
+ for (auto &ext : extents) {
double ext_frag =
std::pow(((double)ext.length / (double)ext_size), (double)i++);
frag_score -= ext_frag;
}
- coll_total += frag_score;
+ coll_total += frag_score;
std::cout << "Object: " << id.hobj.oid.name
<< ", hash: " << id.hobj.get_hash()
<< " fragmentation score: " << frag_score << std::endl;
: c(c_), oid(oid_), exists(exists_), nid(nid_), size(size_) {}
void punch_hole(uint64_t offset, uint64_t length, uint64_t min_alloc_size,
- PExtentVector &old_extents) {
- if (extent_map.empty())
- return;
-
- PExtentVector to_be_punched;
- std::vector<uint64_t> deleted_keys;
- uint64_t end = offset + length;
-
- uint64_t re_add_key{0};
- bluestore_pextent_t re_add;
-
- // std::cout << "current extents:\n";
- // for (auto &[l_off, e] : extent_map) {
- // std::cout << "l_off " << l_off << ", off " << e.offset << ", len "
- // << e.length << std::endl;
- // }
-
- // std::cout << "wants to punch: off " << offset << ", len " << length
- // << std::endl;
-
- auto it = extent_map.lower_bound(offset);
- if ((it == extent_map.end() || it->first > offset) &&
- it != extent_map.begin()) {
- it = std::prev(it);
-
- // diff between where we need to punch and current position
- auto diff = offset - it->first;
- // std::cout << "diff " << diff << " , p_off " << it->first <<
- // std::endl;
-
- // offset will be inside this extent
- // otherwise skip over this extent and assume 'offset' has been passed
- if (diff < it->second.length) {
- // the hole is bigger than the remaining of the extent
- if (end > it->first + it->second.length) {
- to_be_punched.emplace_back(it->second.offset + diff,
- it->second.length - diff);
- } else { // else the hole is entirely in this extent
- to_be_punched.emplace_back(it->second.offset + diff, length);
-
- re_add_key = end;
- re_add.offset = it->second.offset + diff + length;
- re_add.length = it->second.length - diff - length;
-
- // std::cout << "re_add: off " << re_add.offset << ", len "
- // << re_add.length << std::endl;
- }
-
- // Modify the remaining extent's length
- it->second.length = diff;
- }
-
- it++;
- }
-
- // this loop is only valid when 'it' is in the hole
- while (it != extent_map.end() && it->first < end) {
- if (it->first + it->second.length > end) { // last extent to punched
- uint64_t remaining = it->first + it->second.length - end;
- uint64_t punched = it->second.length - remaining;
-
- to_be_punched.emplace_back(it->second.offset, punched);
- deleted_keys.push_back(it->first);
-
- re_add.offset = it->second.offset + punched;
- re_add.length = remaining;
- re_add_key = it->first + punched;
-
- it++;
- break;
- }
-
- deleted_keys.push_back(it->first);
- to_be_punched.push_back(it->second);
- it++;
- }
-
- for (auto k : deleted_keys) {
- extent_map.erase(k);
- }
-
- if (re_add.length > 0) {
- extent_map[re_add_key] = re_add;
- }
-
- old_extents = to_be_punched;
- // std::cout << "to be deleted\n";
- // for (auto e : to_be_punched) {
- // std::cout << "off " << e.offset << ", len " << e.length << std::endl;
- // }
- }
-
- void append(PExtentVector &ext, uint64_t offset) {
- for (auto &e : ext) {
- ceph_assert(e.length > 0);
- // std::cout << "adding off " << offset << ", len " << e.length
- // << std::endl;
- extent_map[offset] = e;
- offset += e.length;
- }
- }
-
- void verify_extents() {
- // std::cout << "verifying extents:\n";
- for (auto &[l_off, ext] : extent_map) {
- // std::cout << l_off << " " << ext.offset << " " << ext.length
- // << std::endl;
- ceph_assert(ext.is_valid());
- ceph_assert(ext.length > 0);
- }
- }
-
- uint64_t ext_length() {
- uint64_t ret{0};
- for (auto &[_, ext] : extent_map) {
- ret += ext.length;
- }
- return ret;
- }
+ PExtentVector &old_extents);
+ void verify_extents();
+ void append(PExtentVector &ext, uint64_t offset);
+ uint64_t ext_length();
};
typedef boost::intrusive_ptr<Object> ObjectRef;