-
Notifications
You must be signed in to change notification settings - Fork 0
test: improve heap_table branch coverage #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
ab02bd9
fix: add StorageManager::delete_file and fix HeapTable::drop path bug
poyrazK 4139e19
test: add 17 new heap_table tests for branch coverage
poyrazK 026bf79
style: automated clang-format fixes
poyrazK 9600ae8
fix: address review comments for heap_table branch coverage PR
poyrazK 05f8287
style: automated clang-format fixes
poyrazK File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial-eviction state leak when a pinned page is encountered mid-iteration.
If the loop has already evicted frames for earlier pages of
file_idand then hits a still-pinned page, the earlyreturn falseon line 242 leaves the buffer pool in an inconsistent state: those earlier frames have already been cleared (file_name_ = "",page_id_ = 0), pushed ontofree_list_, and erased frompage_table_, yet the file has not been deleted and callers are told the operation failed. Subsequent fetches for the still-existing file will silently re-read those pages from disk (OK), but the caller has no way to recover or know which pages were dropped, and the in-flight pinned reader on the remaining page is now operating on a file that the caller is likely about to retry deleting.Prefer a two-pass approach: first scan
page_table_to verify no frame forfile_idhaspin_count_ > 0, then perform the evictions. That keeps the "fails if pinned" contract atomic with respect to buffer-pool state.🛡️ Suggested two-pass implementation
bool BufferPoolManager::delete_file(const std::string& file_name) { { const std::scoped_lock<std::mutex> lock(latch_); const uint32_t file_id = get_file_id_internal(file_name); - // Evict all pages belonging to this file - for (auto it = page_table_.begin(); it != page_table_.end();) { - if (it->first.file_id == file_id) { - const uint32_t frame_id = it->second; - Page* const page = &pages_[frame_id]; - if (page->pin_count_ > 0) { - return false; // Cannot delete while pages are pinned - } - // Flush dirty pages before removing - if (page->is_dirty_) { - storage_manager_.write_page(file_name, page->page_id_, page->get_data()); - page->is_dirty_ = false; - } - replacer_.pin(frame_id); - page->page_id_ = 0; - page->file_name_ = ""; - page->pin_count_ = 0; - free_list_.push_back(frame_id); - it = page_table_.erase(it); - } else { - ++it; - } - } + // First pass: fail fast if any page is still pinned, leaving state untouched. + for (const auto& [key, frame_id] : page_table_) { + if (key.file_id == file_id && pages_[frame_id].pin_count_ > 0) { + return false; + } + } + + // Second pass: evict all matching frames. + for (auto it = page_table_.begin(); it != page_table_.end();) { + if (it->first.file_id != file_id) { + ++it; + continue; + } + const uint32_t frame_id = it->second; + Page* const page = &pages_[frame_id]; + // No need to flush — file is about to be deleted. + replacer_.pin(frame_id); + page->page_id_ = 0; + page->file_name_.clear(); + page->pin_count_ = 0; + page->is_dirty_ = false; + free_list_.push_back(frame_id); + it = page_table_.erase(it); + } // Remove file_id mapping file_id_map_.erase(file_name); } return storage_manager_.delete_file(file_name); }Note: flushing dirty pages right before deleting the file is wasted I/O — the diff above also drops the flush, matching the "is_dirty=false" asymmetry already documented in
HeapTable::drop().🤖 Prompt for AI Agents