From 7d5e1cc393789b8bc24c4aaea2211f9faf11a3c1 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 1 Oct 2023 12:23:37 +0300 Subject: [PATCH] Track blocks per level --- src/kv_db.cpp | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/kv_db.cpp b/src/kv_db.cpp index 4605c640..4aaba470 100644 --- a/src/kv_db.cpp +++ b/src/kv_db.cpp @@ -107,6 +107,7 @@ struct kv_db_t int base_block_level = 0; int usage_counter = 1; + std::set block_levels; std::map block_cache; std::map known_versions; std::multimap> continue_update; @@ -402,6 +403,16 @@ void kv_db_t::stop_updating(kv_block_t *blk) } } +static void del_block_level(kv_db_t *db, kv_block_t *blk) +{ + db->block_levels.erase((((uint64_t)(db->base_block_level+blk->level) & 0xFFFF) << 48) | (blk->offset/db->kv_block_size)); +} + +static void add_block_level(kv_db_t *db, kv_block_t *blk) +{ + db->block_levels.insert((((uint64_t)(db->base_block_level+blk->level) & 0xFFFF) << 48) | (blk->offset/db->kv_block_size)); +} + static void invalidate(kv_db_t *db, uint64_t offset, uint64_t version) { if (db->known_versions[offset/db->ino_block_size] != version) @@ -416,6 +427,8 @@ static void invalidate(kv_db_t *db, uint64_t offset, uint64_t version) } else { + auto blk = &b_it->second; + del_block_level(db, blk); db->block_cache.erase(b_it++); } } @@ -468,6 +481,7 @@ static void get_block(kv_db_t *db, uint64_t offset, int cur_level, int recheck_p blk->offset = op->offset; blk->level = cur_level; blk->usage = db->usage_counter; + add_block_level(db, blk); cb(0, true); } else @@ -703,6 +717,7 @@ static kv_block_t *create_new_block(kv_db_t *db, kv_block_t *old_blk, std::strin blk->data.insert(right ? old_blk->data.lower_bound(separator) : old_blk->data.begin(), right ? old_blk->data.end() : old_blk->data.lower_bound(separator)); blk->set_data_size(); + add_block_level(db, blk); return blk; } @@ -724,6 +739,7 @@ static void write_new_block(kv_db_t *db, kv_block_t *blk, std::functionretval != op->len) { // Failure => free the new unreferenced block and die + del_block_level(db, blk); db->block_cache.erase(blk->offset); cb(op->retval >= 0 ? -EIO : op->retval); return; @@ -740,11 +756,12 @@ static void write_new_block(kv_db_t *db, kv_block_t *blk, std::functionnext_free; db->next_free += db->kv_block_size; db->block_cache[new_offset] = std::move(db->block_cache[blk->offset]); - db->block_cache.erase(blk->offset); auto new_blk = &db->block_cache[new_offset]; *new_blk = *blk; new_blk->offset = new_offset; db->block_cache.erase(blk->offset); + del_block_level(db, blk); + add_block_level(db, new_blk); write_new_block(db, new_blk, cb); } free(op->iov.buf[0].iov_base); @@ -755,6 +772,7 @@ static void write_new_block(kv_db_t *db, kv_block_t *blk, std::function free the new unreferenced block and die + del_block_level(db, blk); db->block_cache.erase(blk->offset); cb(res > 0 ? -EIO : res); } @@ -766,12 +784,12 @@ static void write_new_block(kv_db_t *db, kv_block_t *blk, std::function cb) +static void clear_block(kv_db_t *db, kv_block_t *blk, uint64_t version, std::function cb) { cluster_op_t *op = new cluster_op_t; op->opcode = OSD_OP_WRITE; op->inode = db->inode_id; - op->offset = offset; + op->offset = blk->offset; op->version = version; op->len = db->kv_block_size; op->iov.push_back(malloc_or_die(op->len), op->len); @@ -788,7 +806,8 @@ static void clear_block(kv_db_t *db, uint64_t offset, uint64_t version, std::fun delete op; cb(res); }; - db->block_cache.erase(offset); + del_block_level(db, blk); + db->block_cache.erase(blk->offset); db->cli->execute(op); } @@ -867,6 +886,7 @@ void kv_op_t::create_root() blk->offset = 0; blk->data[key] = value; blk->set_data_size(); + add_block_level(db, blk); write_block(db, blk, [=](int res) { if (res == -EINTR) @@ -1018,13 +1038,14 @@ void kv_op_t::update_block(int path_pos, bool is_delete, const std::string & key db->stop_updating(blk); if (write_res < 0) { - db->base_block_level--; + del_block_level(db, blk); db->block_cache.erase(blk->offset); - clear_block(db, left_blk->offset, 0, [=, left_offset = left_blk->offset](int res) + db->base_block_level--; + clear_block(db, left_blk, 0, [=, left_offset = left_blk->offset](int res) { if (res < 0) fprintf(stderr, "Failed to clear unreferenced block %lu: %s (code %d)\n", left_offset, strerror(-res), res); - clear_block(db, right_blk->offset, 0, [=, right_offset = right_blk->offset](int res) + clear_block(db, right_blk, 0, [=, right_offset = right_blk->offset](int res) { if (res < 0) fprintf(stderr, "Failed to clear unreferenced block %lu: %s (code %d)\n", right_offset, strerror(-res), res); @@ -1062,8 +1083,9 @@ void kv_op_t::update_block(int path_pos, bool is_delete, const std::string & key db->stop_updating(blk); if (write_res < 0) { + del_block_level(db, blk); db->block_cache.erase(blk->offset); - clear_block(db, right_blk->offset, 0, [=, right_offset = right_blk->offset](int res) + clear_block(db, right_blk, 0, [=, right_offset = right_blk->offset](int res) { if (res < 0) fprintf(stderr, "Failed to clear unreferenced block %lu: %s (code %d)\n", right_offset, strerror(-res), res);