Write 1 entry to blocks to collect garbage
This commit is contained in:
@@ -1259,11 +1259,12 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// First try to write into the same block as the previous time
|
// First try to write into the same block as the previous time
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space + inf.garbage_space;
|
if (inf.is_writing ||
|
||||||
if (inf.is_writing || free_space < entry_size ||
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size ||
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
!allow_last_free && meta_nearfull_blocks >= meta_block_count-1 &&
|
!allow_last_free && meta_nearfull_blocks >= meta_block_count-1 &&
|
||||||
free_space >= max_entry_size && free_space < max_entry_size+entry_size)
|
inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
}
|
}
|
||||||
@@ -1280,8 +1281,8 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space + inf.garbage_space;
|
if (inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
if (free_space >= max_entry_size && free_space < max_entry_size+entry_size)
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
}
|
}
|
||||||
@@ -1292,8 +1293,7 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
for (uint32_t b = meta_alloc->find(META_ALLOC_LEVELS-1); b != UINT32_MAX; b = meta_alloc->next(b))
|
for (uint32_t b = meta_alloc->find(META_ALLOC_LEVELS-1); b != UINT32_MAX; b = meta_alloc->next(b))
|
||||||
{
|
{
|
||||||
auto & inf = block_info.at(b);
|
auto & inf = block_info.at(b);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space + inf.garbage_space;
|
if (inf.used_space - inf.garbage_space + entry_size <= dsk->meta_block_size)
|
||||||
if (free_space >= entry_size)
|
|
||||||
{
|
{
|
||||||
last_allocated_block = b;
|
last_allocated_block = b;
|
||||||
break;
|
break;
|
||||||
@@ -1310,8 +1310,8 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
{
|
{
|
||||||
// Do not allow to make the last non-nearfull block nearfull
|
// Do not allow to make the last non-nearfull block nearfull
|
||||||
auto & inf = block_info.at(last_allocated_block);
|
auto & inf = block_info.at(last_allocated_block);
|
||||||
auto free_space = dsk->meta_block_size - inf.used_space + inf.garbage_space;
|
if (inf.used_space - inf.garbage_space <= dsk->meta_block_size-max_entry_size &&
|
||||||
if (free_space >= max_entry_size && free_space+entry_size < max_entry_size)
|
inf.used_space - inf.garbage_space + entry_size > dsk->meta_block_size-max_entry_size)
|
||||||
{
|
{
|
||||||
last_allocated_block = UINT32_MAX;
|
last_allocated_block = UINT32_MAX;
|
||||||
return ENOSPC;
|
return ENOSPC;
|
||||||
@@ -1321,9 +1321,16 @@ int blockstore_heap_t::allocate_entry(uint32_t entry_size, uint32_t *block_num,
|
|||||||
*block_num = last_allocated_block;
|
*block_num = last_allocated_block;
|
||||||
modify_alloc(last_allocated_block, [&](heap_block_info_t & inf)
|
modify_alloc(last_allocated_block, [&](heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
|
// Write just 1 entry to the block to collect garbage
|
||||||
|
if (inf.garbage_space > (inf.used_space-inf.garbage_space)/2)
|
||||||
|
last_allocated_block = UINT32_MAX;
|
||||||
gc_block(inf);
|
gc_block(inf);
|
||||||
inf.used_space += entry_size;
|
inf.used_space += entry_size;
|
||||||
assert(inf.used_space - inf.garbage_space <= dsk->meta_block_size);
|
assert(inf.used_space - inf.garbage_space <= dsk->meta_block_size);
|
||||||
|
assert(!inf.mod_lsn_to || inf.mod_lsn_to == next_lsn);
|
||||||
|
++next_lsn;
|
||||||
|
inf.mod_lsn = inf.mod_lsn ? inf.mod_lsn : next_lsn;
|
||||||
|
inf.mod_lsn_to = next_lsn;
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1389,11 +1396,8 @@ int blockstore_heap_t::add_entry(uint32_t wr_size, uint32_t *modified_block,
|
|||||||
if (!inf.entries.size())
|
if (!inf.entries.size())
|
||||||
inf.entries.reserve(dsk->meta_block_size / max_entry_size);
|
inf.entries.reserve(dsk->meta_block_size / max_entry_size);
|
||||||
inf.entries.push_back(li);
|
inf.entries.push_back(li);
|
||||||
assert(!inf.mod_lsn_to || inf.mod_lsn_to == next_lsn);
|
new_wr->lsn = next_lsn;
|
||||||
new_wr->lsn = ++next_lsn;
|
|
||||||
fill_entry(new_wr);
|
fill_entry(new_wr);
|
||||||
inf.mod_lsn = inf.mod_lsn ? inf.mod_lsn : next_lsn;
|
|
||||||
inf.mod_lsn_to = next_lsn;
|
|
||||||
// Remember the object as dirty and remove older entries when this block is written and fsynced
|
// Remember the object as dirty and remove older entries when this block is written and fsynced
|
||||||
push_inflight_lsn(next_lsn, new_wr,
|
push_inflight_lsn(next_lsn, new_wr,
|
||||||
(explicit_complete ? HEAP_INFLIGHT_EXPLICIT : 0) |
|
(explicit_complete ? HEAP_INFLIGHT_EXPLICIT : 0) |
|
||||||
@@ -1733,7 +1737,7 @@ int blockstore_heap_t::add_delete(heap_entry_t *obj, uint32_t *modified_block)
|
|||||||
uint32_t blockstore_heap_t::meta_alloc_pos(const heap_block_info_t & inf)
|
uint32_t blockstore_heap_t::meta_alloc_pos(const heap_block_info_t & inf)
|
||||||
{
|
{
|
||||||
auto real_used = (inf.used_space-inf.garbage_space);
|
auto real_used = (inf.used_space-inf.garbage_space);
|
||||||
if (inf.is_writing || real_used > dsk->meta_block_size-sizeof(heap_entry_t))
|
if (inf.is_writing || inf.mod_lsn || real_used > dsk->meta_block_size-sizeof(heap_entry_t))
|
||||||
{
|
{
|
||||||
// 100% full - no entry can be written into this block at all
|
// 100% full - no entry can be written into this block at all
|
||||||
return META_ALLOC_LEVELS;
|
return META_ALLOC_LEVELS;
|
||||||
@@ -1775,11 +1779,19 @@ void blockstore_heap_t::modify_alloc(uint32_t block_num, std::function<void(heap
|
|||||||
|
|
||||||
void blockstore_heap_t::start_block_write(uint32_t block_num)
|
void blockstore_heap_t::start_block_write(uint32_t block_num)
|
||||||
{
|
{
|
||||||
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
auto & inf = block_info.at(block_num);
|
||||||
|
assert(!inf.is_writing);
|
||||||
|
if (!inf.mod_lsn)
|
||||||
|
{
|
||||||
|
modify_alloc(block_num, [&](heap_block_info_t & inf)
|
||||||
|
{
|
||||||
|
inf.is_writing = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
assert(!inf.is_writing);
|
|
||||||
inf.is_writing = true;
|
inf.is_writing = true;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockstore_heap_t::complete_block_write(uint32_t block_num)
|
void blockstore_heap_t::complete_block_write(uint32_t block_num)
|
||||||
|
|||||||
Reference in New Issue
Block a user