-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor(p2): remove transaction from b plus tree * sync b_plus_tree.h function param * sync b plus tree function header * rm txn in btree bench * nits * decouple b plus tree debugging tool * split array into two * fix make error * fix debugging tool function param * nits * fix linting * fix linting * fix file path * linting * linting * Modify P2 tests * fix concurrent test * fix clang-tidy * Modify header size * Update comments * sync with private repo * rm comments for task 2.a * fix style of debug functions * Apply comment suggestions * change val arr name; enlarge bench bpm size --------- Co-authored-by: Lan Lou <[email protected]> Co-authored-by: Lan Lou <[email protected]>
- Loading branch information
1 parent
bd6c48e
commit c4f96a1
Showing
22 changed files
with
820 additions
and
698 deletions.
There are no files selected for viewing
This file contains 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 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 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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// BusTub | ||
// | ||
// b_plus_tree_debug.h | ||
// | ||
// Identification: bustub/src/include/storage/index/b_plus_tree_debug.h | ||
// | ||
// Copyright (c) 2024, Carnegie Mellon University Database Group | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <sstream> | ||
#include <string> | ||
|
||
#include "common/exception.h" | ||
#include "common/logger.h" | ||
#include "common/rid.h" | ||
#include "storage/index/b_plus_tree.h" | ||
#include "storage/page/b_plus_tree_page.h" | ||
|
||
namespace bustub { | ||
|
||
/* | ||
* All the methods in this file are used for test and debug only. | ||
* You don't need to modify them. | ||
*/ | ||
|
||
/***************************************************************************** | ||
* UTILITIES AND DEBUG | ||
*****************************************************************************/ | ||
|
||
/* | ||
* This method is used for test only | ||
* Read data from file and insert one by one | ||
*/ | ||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::InsertFromFile(const std::filesystem::path &file_name) { | ||
int64_t key; | ||
std::ifstream input(file_name); | ||
while (input) { | ||
input >> key; | ||
|
||
KeyType index_key; | ||
index_key.SetFromInteger(key); | ||
RID rid(key); | ||
Insert(index_key, rid); | ||
} | ||
} | ||
/* | ||
* This method is used for test only | ||
* Read data from file and remove one by one | ||
*/ | ||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::RemoveFromFile(const std::filesystem::path &file_name) { | ||
int64_t key; | ||
std::ifstream input(file_name); | ||
while (input) { | ||
input >> key; | ||
KeyType index_key; | ||
index_key.SetFromInteger(key); | ||
Remove(index_key); | ||
} | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::Print(BufferPoolManager *bpm) { | ||
auto root_page_id = GetRootPageId(); | ||
if (root_page_id != INVALID_PAGE_ID) { | ||
auto guard = bpm->ReadPage(root_page_id); | ||
PrintTree(guard.GetPageId(), guard.template As<BPlusTreePage>()); | ||
} | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::PrintTree(page_id_t page_id, const BPlusTreePage *page) { | ||
if (page->IsLeafPage()) { | ||
auto *leaf = reinterpret_cast<const LeafPage *>(page); | ||
std::cout << "Leaf Page: " << page_id << "\tNext: " << leaf->GetNextPageId() << std::endl; | ||
|
||
// Print the contents of the leaf page. | ||
std::cout << "Contents: "; | ||
for (int i = 0; i < leaf->GetSize(); i++) { | ||
std::cout << leaf->KeyAt(i); | ||
if ((i + 1) < leaf->GetSize()) { | ||
std::cout << ", "; | ||
} | ||
} | ||
std::cout << std::endl; | ||
std::cout << std::endl; | ||
|
||
} else { | ||
auto *internal = reinterpret_cast<const InternalPage *>(page); | ||
std::cout << "Internal Page: " << page_id << std::endl; | ||
|
||
// Print the contents of the internal page. | ||
std::cout << "Contents: "; | ||
for (int i = 0; i < internal->GetSize(); i++) { | ||
if (i == 0) { | ||
std::cout << internal->ValueAt(i); | ||
} else { | ||
std::cout << internal->KeyAt(i) << ": " << internal->ValueAt(i); | ||
} | ||
if ((i + 1) < internal->GetSize()) { | ||
std::cout << ", "; | ||
} | ||
} | ||
std::cout << std::endl; | ||
std::cout << std::endl; | ||
for (int i = 0; i < internal->GetSize(); i++) { | ||
auto guard = bpm_->ReadPage(internal->ValueAt(i)); | ||
PrintTree(guard.GetPageId(), guard.template As<BPlusTreePage>()); | ||
} | ||
} | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::Draw(BufferPoolManager *bpm, const std::filesystem::path &outf) { | ||
if (IsEmpty()) { | ||
LOG_WARN("Drawing an empty tree"); | ||
return; | ||
} | ||
|
||
std::ofstream out(outf); | ||
out << "digraph G {" << std::endl; | ||
auto root_page_id = GetRootPageId(); | ||
auto guard = bpm->ReadPage(root_page_id); | ||
ToGraph(guard.GetPageId(), guard.template As<BPlusTreePage>(), out); | ||
out << "}" << std::endl; | ||
out.close(); | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::ToGraph(page_id_t page_id, const BPlusTreePage *page, std::ofstream &out) { | ||
std::string leaf_prefix("LEAF_"); | ||
std::string internal_prefix("INT_"); | ||
if (page->IsLeafPage()) { | ||
auto *leaf = reinterpret_cast<const LeafPage *>(page); | ||
// Print node name | ||
out << leaf_prefix << page_id; | ||
// Print node properties | ||
out << "[shape=plain color=green "; | ||
// Print data of the node | ||
out << "label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\n"; | ||
// Print data | ||
out << "<TR><TD COLSPAN=\"" << leaf->GetSize() << "\">P=" << page_id << "</TD></TR>\n"; | ||
out << "<TR><TD COLSPAN=\"" << leaf->GetSize() << "\">" | ||
<< "max_size=" << leaf->GetMaxSize() << ",min_size=" << leaf->GetMinSize() << ",size=" << leaf->GetSize() | ||
<< "</TD></TR>\n"; | ||
out << "<TR>"; | ||
for (int i = 0; i < leaf->GetSize(); i++) { | ||
out << "<TD>" << leaf->KeyAt(i) << "</TD>\n"; | ||
} | ||
out << "</TR>"; | ||
// Print table end | ||
out << "</TABLE>>];\n"; | ||
// Print Leaf node link if there is a next page | ||
if (leaf->GetNextPageId() != INVALID_PAGE_ID) { | ||
out << leaf_prefix << page_id << " -> " << leaf_prefix << leaf->GetNextPageId() << ";\n"; | ||
out << "{rank=same " << leaf_prefix << page_id << " " << leaf_prefix << leaf->GetNextPageId() << "};\n"; | ||
} | ||
} else { | ||
auto *inner = reinterpret_cast<const InternalPage *>(page); | ||
// Print node name | ||
out << internal_prefix << page_id; | ||
// Print node properties | ||
out << "[shape=plain color=pink "; // why not? | ||
// Print data of the node | ||
out << "label=<<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\n"; | ||
// Print data | ||
out << "<TR><TD COLSPAN=\"" << inner->GetSize() << "\">P=" << page_id << "</TD></TR>\n"; | ||
out << "<TR><TD COLSPAN=\"" << inner->GetSize() << "\">" | ||
<< "max_size=" << inner->GetMaxSize() << ",min_size=" << inner->GetMinSize() << ",size=" << inner->GetSize() | ||
<< "</TD></TR>\n"; | ||
out << "<TR>"; | ||
for (int i = 0; i < inner->GetSize(); i++) { | ||
out << "<TD PORT=\"p" << inner->ValueAt(i) << "\">"; | ||
if (i > 0) { | ||
out << inner->KeyAt(i); | ||
} else { | ||
out << " "; | ||
} | ||
out << "</TD>\n"; | ||
} | ||
out << "</TR>"; | ||
// Print table end | ||
out << "</TABLE>>];\n"; | ||
// Print leaves | ||
for (int i = 0; i < inner->GetSize(); i++) { | ||
auto child_guard = bpm_->ReadPage(inner->ValueAt(i)); | ||
auto child_page = child_guard.template As<BPlusTreePage>(); | ||
ToGraph(child_guard.GetPageId(), child_page, out); | ||
if (i > 0) { | ||
auto sibling_guard = bpm_->ReadPage(inner->ValueAt(i - 1)); | ||
auto sibling_page = sibling_guard.template As<BPlusTreePage>(); | ||
if (!sibling_page->IsLeafPage() && !child_page->IsLeafPage()) { | ||
out << "{rank=same " << internal_prefix << sibling_guard.GetPageId() << " " << internal_prefix | ||
<< child_guard.GetPageId() << "};\n"; | ||
} | ||
} | ||
out << internal_prefix << page_id << ":p" << child_guard.GetPageId() << " -> "; | ||
if (child_page->IsLeafPage()) { | ||
out << leaf_prefix << child_guard.GetPageId() << ";\n"; | ||
} else { | ||
out << internal_prefix << child_guard.GetPageId() << ";\n"; | ||
} | ||
} | ||
} | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
auto BPLUSTREE_TYPE::DrawBPlusTree() -> std::string { | ||
if (IsEmpty()) { | ||
return "()"; | ||
} | ||
|
||
PrintableBPlusTree p_root = ToPrintableBPlusTree(GetRootPageId()); | ||
std::ostringstream out_buf; | ||
p_root.Print(out_buf); | ||
|
||
return out_buf.str(); | ||
} | ||
|
||
/* | ||
* This method is used for test only | ||
* Read data from file and insert/remove one by one | ||
*/ | ||
INDEX_TEMPLATE_ARGUMENTS | ||
void BPLUSTREE_TYPE::BatchOpsFromFile(const std::filesystem::path &file_name) { | ||
int64_t key; | ||
char instruction; | ||
std::ifstream input(file_name); | ||
while (input) { | ||
input >> instruction >> key; | ||
RID rid(key); | ||
KeyType index_key; | ||
index_key.SetFromInteger(key); | ||
switch (instruction) { | ||
case 'i': | ||
Insert(index_key, rid); | ||
break; | ||
case 'd': | ||
Remove(index_key); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
|
||
INDEX_TEMPLATE_ARGUMENTS | ||
auto BPLUSTREE_TYPE::ToPrintableBPlusTree(page_id_t root_id) -> PrintableBPlusTree { | ||
auto root_page_guard = bpm_->ReadPage(root_id); | ||
auto root_page = root_page_guard.template As<BPlusTreePage>(); | ||
PrintableBPlusTree proot; | ||
|
||
if (root_page->IsLeafPage()) { | ||
auto leaf_page = root_page_guard.template As<LeafPage>(); | ||
proot.keys_ = leaf_page->ToString(); | ||
proot.size_ = proot.keys_.size() + 4; // 4 more spaces for indent | ||
|
||
return proot; | ||
} | ||
|
||
// draw internal page | ||
auto internal_page = root_page_guard.template As<InternalPage>(); | ||
proot.keys_ = internal_page->ToString(); | ||
proot.size_ = 0; | ||
for (int i = 0; i < internal_page->GetSize(); i++) { | ||
page_id_t child_id = internal_page->ValueAt(i); | ||
PrintableBPlusTree child_node = ToPrintableBPlusTree(child_id); | ||
proot.size_ += child_node.size_; | ||
proot.children_.push_back(child_node); | ||
} | ||
|
||
return proot; | ||
} | ||
} // namespace bustub |
This file contains 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.