return empty;
}
+
+std::pair<uint32_t, uint32_t> bluestore_blob_use_tracker_t::put_simple(
+ uint32_t offset, uint32_t length)
+{
+ if (num_au == 0) {
+ // single tracker for entire blob
+ ceph_assert(total_bytes >= length);
+ total_bytes -= length;
+ if (total_bytes == 0) {
+ return std::make_pair(0, au_size);
+ } else {
+ return std::make_pair(0, 0);
+ }
+ } else {
+ uint32_t clear_start = 0;
+ uint32_t clear_end = 0;
+ uint32_t pos = offset / au_size;
+ uint32_t remain = p2remain(offset, au_size);
+ if (length <= remain) {
+ // all in same block
+ ceph_assert(length <= bytes_per_au[pos]);
+ bytes_per_au[pos] -= length;
+ if (bytes_per_au[pos] == 0) {
+ clear_start = pos * au_size;
+ clear_end = clear_start + au_size;
+ }
+ } else {
+ // length > remain
+ ceph_assert(remain <= bytes_per_au[pos]);
+ bytes_per_au[pos] -= remain;
+ if (bytes_per_au[pos] == 0) {
+ clear_start = pos * au_size;
+ } else {
+ clear_start = (pos + 1) * au_size;
+ }
+ ++pos;
+ length -= remain;
+ while (length >= au_size) {
+ ceph_assert(au_size == bytes_per_au[pos]);
+ bytes_per_au[pos] = 0;
+ ++pos;
+ length -= au_size;
+ }
+ if (length > 0) {
+ ceph_assert(length <= bytes_per_au[pos]);
+ bytes_per_au[pos] -= length;
+ if (bytes_per_au[pos] == 0) {
+ ++pos;
+ }
+ }
+ clear_end = pos * au_size;
+ }
+ return std::make_pair(clear_start, clear_end - clear_start);
+ }
+}
+
bool bluestore_blob_use_tracker_t::can_split() const
{
return num_au > 0;
)
);
+class bluestore_blob_use_tracker_t_test :
+ public ::testing::Test,
+ public ::testing::WithParamInterface<std::vector<int>>
+{
+};
+
+TEST_P(bluestore_blob_use_tracker_t_test, put_simple)
+{
+ // generate offset / length
+ // get region [offset~length] in tracker
+ // choose randomly x points in range [offset~length]
+ // in random order
+ // put them into tracker
+ // check if all is cleared as it should
+
+ std::vector<int> param = GetParam();
+ ASSERT_EQ(param.size(), 6);
+ uint32_t alloc_unit = param[0];
+ uint32_t test_size_range = param[1];
+ uint32_t test_offset_range = param[2];
+ uint32_t test_offset_length = param[3];
+ uint32_t test_aligned_nom = param[4];
+ uint32_t test_aligned_denom = param[5];
+
+ auto rand_next = [&](uint32_t prev) -> uint32_t {
+ uint32_t next;
+ uint32_t len = rand() % test_size_range + 1;
+ if (rand() % test_aligned_denom < test_aligned_nom) {
+ // go for aligned
+ next = p2roundup(prev + len, alloc_unit);
+ } else {
+ // unaligned
+ next = prev + len;
+ }
+ return next;
+ };
+ auto rand_pos = [&](uint32_t range) -> uint32_t {
+ if (rand() % test_aligned_denom < test_aligned_nom) {
+ return p2align(rand() % range, alloc_unit);
+ } else {
+ return rand() % range;
+ }
+ };
+
+ for (int k = 0; k < 10000; k++) {
+ std::map<int, std::pair<int, int>> regions;
+ uint32_t offset = rand_pos(test_offset_range);
+ uint32_t length = 0;
+ while (length == 0) {
+ length = rand_pos(test_offset_length);
+ }
+ //std::cout << std::hex << "offset=" << offset
+ // << " length=" << length << std::dec << std::endl;
+ uint32_t i = offset;
+ uint32_t j = offset;
+ while (i < offset + length) {
+ j = rand_next(i);
+ if (j > offset + length)
+ j = offset + length;
+ regions[rand() * 10000 + regions.size()] = std::make_pair(i, j - i);
+ i = j;
+ }
+ bluestore_blob_use_tracker_t t;
+ t.init(offset + length, alloc_unit);
+ t.get(offset, length);
+
+ interval_set<uint32_t> released;
+ for (auto r : regions) {
+ auto v = t.put_simple(r.second.first, r.second.second);
+ //std::cout << std::hex << "0x" << r.second.first << "~" << r.second.second
+ // << "->0x" << v.first << "~" << v.second << std::dec << std::endl;
+ if (v.second > 0) {
+ released.insert(v.first, v.second);
+ }
+ }
+ ASSERT_FALSE(released.empty());
+ ASSERT_EQ(t.get_referenced_bytes(), 0);
+ ASSERT_EQ(released.begin().get_start(), p2align(offset, alloc_unit));
+ ASSERT_EQ(released.begin().get_end(), p2roundup(offset + length, alloc_unit));
+ }
+}
+
+/*
+ uint32_t alloc_unit = 4096;
+ uint32_t test_size_range = 10000;
+ uint32_t test_offset_range = 50000;
+ uint32_t test_offset_length = 100000;
+ uint32_t test_aligned_denom = 3;
+ uint32_t test_aligned_nom = 2;
+*/
+INSTANTIATE_TEST_SUITE_P(
+ BlueStore,
+ bluestore_blob_use_tracker_t_test,
+ ::testing::Values(
+ std::vector<int>({4096, 10000, 50000, 100000, 2, 3}),
+ std::vector<int>({4096, 10000, 40000, 80000, 1, 11}),
+ std::vector<int>({8192, 30000, 80000, 160000, 2, 4}),
+ std::vector<int>({32768, 40000, 80000, 160000, 5, 6})
+ )
+);
+
+
//---------------------------------------------------------------------------------
static int verify_extent(const extent_t &ext, const extent_t *ext_arr,
uint64_t ext_arr_size, uint64_t idx) {