Sort items on load to fix O(N^2) startup
This commit is contained in:
@@ -360,7 +360,7 @@ corrupted_object:
|
||||
{
|
||||
// Small writes require accessing offset & len to calculate correct length,
|
||||
// so require at least sizeof(heap_small_write_t) for them
|
||||
fprintf(stderr, "Error: entry %jx:%jx v%ju has invalid size in metadata block %u at %u (%u < min %zu bytes). Metadata is corrupted, aborting\n",
|
||||
fprintf(stderr, "Error: entry %jx:%jx v%ju has invalid size in metadata block %u at %u (%u < min %zu bytes)\n",
|
||||
wr->inode, wr->stripe, wr->version, block_num, block_offset, wr->size, sizeof(heap_small_write_t));
|
||||
goto corrupted_object;
|
||||
}
|
||||
@@ -374,7 +374,7 @@ corrupted_object:
|
||||
uint32_t expected_crc32c = wr->calc_crc32c();
|
||||
if (wr->crc32c != expected_crc32c)
|
||||
{
|
||||
fprintf(stderr, "Error: entry %jx:%jx v%ju in metadata block %u at %u is corrupt (crc32c mismatch: expected %08x, got %08x). Metadata is corrupted, aborting\n",
|
||||
fprintf(stderr, "Error: entry %jx:%jx v%ju in metadata block %u at %u is corrupt (crc32c mismatch: expected %08x, got %08x). ",
|
||||
wr->inode, wr->stripe, wr->version,
|
||||
block_num, block_offset, expected_crc32c, wr->crc32c);
|
||||
goto corrupted_object;
|
||||
@@ -385,7 +385,7 @@ corrupted_object:
|
||||
wr->small().offset % dsk->bitmap_granularity ||
|
||||
wr->small().len % dsk->bitmap_granularity))
|
||||
{
|
||||
fprintf(stderr, "Error: %s entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters, aborting\n",
|
||||
fprintf(stderr, "Error: %s entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters. ",
|
||||
wr->type() == BS_HEAP_SMALL_WRITE ? "small_write" : "intent_write",
|
||||
wr->inode, wr->stripe, wr->version, wr->small().offset, wr->small().len);
|
||||
goto corrupted_object;
|
||||
@@ -395,7 +395,7 @@ corrupted_object:
|
||||
wr->big_intent().offset % dsk->bitmap_granularity ||
|
||||
wr->big_intent().len % dsk->bitmap_granularity))
|
||||
{
|
||||
fprintf(stderr, "Error: big_intent entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters, aborting\n",
|
||||
fprintf(stderr, "Error: big_intent entry %jx:%jx v%ju has invalid offset/length: %u/%u. Metadata is incompatible with current parameters. ",
|
||||
wr->inode, wr->stripe, wr->version, wr->big_intent().offset, wr->big_intent().len);
|
||||
goto corrupted_object;
|
||||
}
|
||||
@@ -422,7 +422,7 @@ int blockstore_heap_t::load_blocks(uint64_t disk_offset, uint64_t size, uint8_t
|
||||
next_lsn = wr->lsn;
|
||||
}
|
||||
entries_loaded++;
|
||||
insert_list_item(li);
|
||||
loaded_list_items.push_back(li);
|
||||
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||
{
|
||||
if (!inf.entries.size())
|
||||
@@ -526,6 +526,23 @@ bool blockstore_heap_t::validate_object(heap_entry_t *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
void blockstore_heap_t::finish_load()
|
||||
{
|
||||
if (loaded_list_items.size())
|
||||
{
|
||||
// Sort everything and load in correct order
|
||||
std::sort(loaded_list_items.begin(), loaded_list_items.end(), [this](const heap_list_item_t* a, const heap_list_item_t* b)
|
||||
{
|
||||
return a->entry.lsn < b->entry.lsn;
|
||||
});
|
||||
for (auto & li: loaded_list_items)
|
||||
{
|
||||
insert_list_item(li);
|
||||
}
|
||||
loaded_list_items.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void blockstore_heap_t::fill_recheck_queue()
|
||||
{
|
||||
for (auto & pgp: block_index)
|
||||
@@ -712,6 +729,7 @@ bool blockstore_heap_t::recheck_small_writes(std::function<void(bool is_data, ui
|
||||
}
|
||||
if (!recheck_queue_filled)
|
||||
{
|
||||
finish_load();
|
||||
fill_recheck_queue();
|
||||
recheck_queue_filled = true;
|
||||
}
|
||||
@@ -803,7 +821,7 @@ std::vector<uint32_t> blockstore_heap_t::get_recheck_modified_blocks()
|
||||
return modified;
|
||||
}
|
||||
|
||||
int blockstore_heap_t::finish_load(bool allow_corrupted)
|
||||
int blockstore_heap_t::finish_recheck()
|
||||
{
|
||||
if (!marked_used_blocks)
|
||||
{
|
||||
|
||||
@@ -200,6 +200,7 @@ class blockstore_heap_t
|
||||
|
||||
bool marked_used_blocks = false;
|
||||
bool recheck_queue_filled = false;
|
||||
std::vector<heap_list_item_t*> loaded_list_items;
|
||||
std::set<uint32_t> recheck_modified_blocks;
|
||||
std::deque<heap_entry_t*> recheck_queue;
|
||||
int recheck_in_progress = 0;
|
||||
@@ -237,13 +238,14 @@ public:
|
||||
std::function<void(uint32_t, uint32_t, uint8_t*)> handle_block);
|
||||
int load_blocks(uint64_t disk_offset, uint64_t size, uint8_t *buf,
|
||||
bool allow_corrupted, uint64_t &entries_loaded);
|
||||
// finish loading
|
||||
int finish_load(bool allow_corrupted = false);
|
||||
// finish loading - should be called after load_blocks
|
||||
void finish_load();
|
||||
// get blocks which are modified during loading and should be written to the disk
|
||||
// before finishing initialization if not R/O
|
||||
std::vector<uint32_t> get_recheck_modified_blocks();
|
||||
// recheck small write data after reading the database from disk
|
||||
bool recheck_small_writes(std::function<void(bool is_data, uint64_t offset, uint64_t len, uint8_t* buf, std::function<void()>)> read_buffer, int queue_depth);
|
||||
int finish_recheck();
|
||||
// reshard database according to the pool's PG count
|
||||
void* reshard_start(pool_id_t pool, uint32_t pg_count, uint32_t pg_stripe_size, uint64_t chunk_limit);
|
||||
bool reshard_continue(void* reshard_state, uint64_t chunk_limit);
|
||||
|
||||
@@ -239,6 +239,7 @@ resume_4:
|
||||
return 1;
|
||||
}
|
||||
// metadata read finished
|
||||
bs->heap->finish_load();
|
||||
printf("Metadata entries loaded: %ju, used blocks: %ju / %ju\n", entries_loaded, bs->heap->get_data_used_space() / bs->dsk.data_block_size, bs->dsk.block_count);
|
||||
if (zero_on_init && !bs->dsk.disable_meta_fsync)
|
||||
{
|
||||
@@ -284,7 +285,7 @@ resume_6:
|
||||
}, bs->meta_write_recheck_parallelism);
|
||||
return 1;
|
||||
resume_7:
|
||||
if (bs->heap->finish_load() != 0)
|
||||
if (bs->heap->finish_recheck() != 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user