More fixes
- do not overwrite a block with older version if known version is newer (read may start before update and end after update) - invalidated block versions can't be remembered and trusted - right boundary for split blocks is right_half when diving down, not key_lt - restart update also when block is "invalidated", not just on version mismatch - copy callback in listings to avoid closure destruction bugs tookv-debug
parent
c5b00f897a
commit
13e2d3ce7c
|
@ -842,7 +842,8 @@ static void get_block(kv_db_t *db, uint64_t offset, int cur_level, int recheck_p
|
||||||
invalidate(db, op->offset, op->version);
|
invalidate(db, op->offset, op->version);
|
||||||
auto blk_it = db->block_cache.find(op->offset);
|
auto blk_it = db->block_cache.find(op->offset);
|
||||||
if (blk_it != db->block_cache.end() &&
|
if (blk_it != db->block_cache.end() &&
|
||||||
(db->known_versions[op->offset/db->ino_block_size] == op->version || blk_it->second.updating > 0))
|
// read may start BEFORE update and end AFTER update, in this case known will be > returned version
|
||||||
|
(db->known_versions[op->offset/db->ino_block_size] >= op->version && !blk_it->second.invalidated || blk_it->second.updating > 0))
|
||||||
{
|
{
|
||||||
auto blk = &db->block_cache.at(op->offset);
|
auto blk = &db->block_cache.at(op->offset);
|
||||||
if (blk->updating > 0 && recheck_policy == KV_RECHECK_WAIT)
|
if (blk->updating > 0 && recheck_policy == KV_RECHECK_WAIT)
|
||||||
|
@ -987,7 +988,7 @@ int kv_op_t::handle_block(int res, int refresh, bool stop_on_split)
|
||||||
// and recheck parent blocks if their versions change. This is required
|
// and recheck parent blocks if their versions change. This is required
|
||||||
// because we have to handle parallel splits of parent blocks correctly
|
// because we have to handle parallel splits of parent blocks correctly
|
||||||
assert(path.size() > 0);
|
assert(path.size() > 0);
|
||||||
path[path.size()-1].version = db->known_versions[cur_block/db->ino_block_size];
|
path[path.size()-1].version = blk->invalidated ? 0 : db->known_versions[cur_block/db->ino_block_size];
|
||||||
}
|
}
|
||||||
if (key < blk->key_ge || blk->key_lt.size() && key >= blk->key_lt)
|
if (key < blk->key_ge || blk->key_lt.size() && key >= blk->key_lt)
|
||||||
{
|
{
|
||||||
|
@ -1071,7 +1072,9 @@ int kv_op_t::handle_block(int res, int refresh, bool stop_on_split)
|
||||||
fprintf(stderr, "K/V: Internal block %lu misses boundary for %s\n", cur_block, key.c_str());
|
fprintf(stderr, "K/V: Internal block %lu misses boundary for %s\n", cur_block, key.c_str());
|
||||||
return -EILSEQ;
|
return -EILSEQ;
|
||||||
}
|
}
|
||||||
auto m = child_it == blk->data.end() ? blk->key_lt : child_it->first;
|
auto m = child_it == blk->data.end()
|
||||||
|
? (blk->type == KV_LEAF_SPLIT || blk->type == KV_INT_SPLIT
|
||||||
|
? blk->right_half : blk->key_lt) : child_it->first;
|
||||||
child_it--;
|
child_it--;
|
||||||
if (child_it->second.size() != sizeof(uint64_t))
|
if (child_it->second.size() != sizeof(uint64_t))
|
||||||
{
|
{
|
||||||
|
@ -1464,7 +1467,7 @@ void kv_op_t::update_block(int path_pos, bool is_delete, const std::string & key
|
||||||
db->continue_update.emplace(blk->offset, [=]() { update_block(path_pos, is_delete, key, value, cb); });
|
db->continue_update.emplace(blk->offset, [=]() { update_block(path_pos, is_delete, key, value, cb); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (db->known_versions[blk->offset/db->ino_block_size] != block_ver)
|
if (db->known_versions[blk->offset/db->ino_block_size] != block_ver || blk->invalidated)
|
||||||
{
|
{
|
||||||
// Recheck if block was modified in the meantime
|
// Recheck if block was modified in the meantime
|
||||||
db->run_continue_update(blk->offset);
|
db->run_continue_update(blk->offset);
|
||||||
|
@ -1766,7 +1769,7 @@ void kv_op_t::next_get()
|
||||||
this->key = kv_it->first;
|
this->key = kv_it->first;
|
||||||
this->value = kv_it->second;
|
this->value = kv_it->second;
|
||||||
skip_equal = true;
|
skip_equal = true;
|
||||||
callback(this);
|
(std::function<void(kv_op_t *)>(callback))(this);
|
||||||
}
|
}
|
||||||
// Find next block
|
// Find next block
|
||||||
else if (blk->type == KV_LEAF_SPLIT)
|
else if (blk->type == KV_LEAF_SPLIT)
|
||||||
|
|
Loading…
Reference in New Issue