diff --git a/Tests/LibSQL/TestSqlHeap.cpp b/Tests/LibSQL/TestSqlHeap.cpp index c47b2bda47..eb02d58e2f 100644 --- a/Tests/LibSQL/TestSqlHeap.cpp +++ b/Tests/LibSQL/TestSqlHeap.cpp @@ -167,3 +167,27 @@ TEST_CASE(heap_reuse_freed_blocks_after_reopening_file) EXPECT(heap_size_after_second_storage <= original_heap_size); } } + +TEST_CASE(heap_free_storage) +{ + ScopeGuard guard([]() { MUST(Core::System::unlink(db_path)); }); + auto heap = create_heap(); + auto storage_block_id = heap->request_new_block_index(); + + // Write large storage spanning multiple blocks + StringBuilder builder; + MUST(builder.try_append_repeated('x', SQL::Block::DATA_SIZE * 4)); + auto long_string = builder.string_view(); + TRY_OR_FAIL(heap->write_storage(storage_block_id, long_string.bytes())); + MUST(heap->flush()); + auto heap_size = MUST(heap->file_size_in_bytes()); + + // Free the storage + TRY_OR_FAIL(heap->free_storage(storage_block_id)); + + // Again, write some large storage spanning multiple blocks + TRY_OR_FAIL(heap->write_storage(storage_block_id, long_string.bytes())); + MUST(heap->flush()); + auto new_heap_size = MUST(heap->file_size_in_bytes()); + EXPECT(new_heap_size <= heap_size); +} diff --git a/Userland/Libraries/LibSQL/Heap.cpp b/Userland/Libraries/LibSQL/Heap.cpp index b373d78081..ac20aa5b8f 100644 --- a/Userland/Libraries/LibSQL/Heap.cpp +++ b/Userland/Libraries/LibSQL/Heap.cpp @@ -154,11 +154,8 @@ ErrorOr Heap::write_storage(Block::Index index, ReadonlyBytes data) } // Free remaining blocks in existing chain, if any - while (existing_next_block_index > 0) { - auto existing_block = TRY(read_block(existing_next_block_index)); - existing_next_block_index = existing_block.next_block(); - TRY(free_block(existing_block)); - } + if (existing_next_block_index > 0) + TRY(free_storage(existing_next_block_index)); return {}; } @@ -235,6 +232,19 @@ ErrorOr Heap::write_block(Block const& block) return write_raw_block_to_wal(block.index(), move(heap_data)); } +ErrorOr Heap::free_storage(Block::Index index) +{ + dbgln_if(SQL_DEBUG, "{}({})", __FUNCTION__, index); + VERIFY(index > 0); + + while (index > 0) { + auto block = TRY(read_block(index)); + TRY(free_block(block)); + index = block.next_block(); + } + return {}; +} + ErrorOr Heap::free_block(Block const& block) { auto index = block.index(); diff --git a/Userland/Libraries/LibSQL/Heap.h b/Userland/Libraries/LibSQL/Heap.h index c583780a13..398e25918e 100644 --- a/Userland/Libraries/LibSQL/Heap.h +++ b/Userland/Libraries/LibSQL/Heap.h @@ -116,6 +116,7 @@ public: ErrorOr read_storage(Block::Index); ErrorOr write_storage(Block::Index, ReadonlyBytes); + ErrorOr free_storage(Block::Index); ErrorOr flush();