Skip to content

Commit

Permalink
refactor(p2): fall 2024 (#754)
Browse files Browse the repository at this point in the history
* 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 <lanlou1554@gmail.com>
Co-authored-by: Lan Lou <62441979+lanlou1554@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 30, 2024
1 parent bd6c48e commit c4f96a1
Show file tree
Hide file tree
Showing 22 changed files with 820 additions and 698 deletions.
21 changes: 11 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,17 @@ add_custom_target(submit-p1
)

set(P2_FILES
"src/include/storage/page/page_guard.h"
"src/storage/page/page_guard.cpp"
"src/include/storage/page/extendible_htable_bucket_page.h"
"src/storage/page/extendible_htable_bucket_page.cpp"
"src/include/storage/page/extendible_htable_directory_page.h"
"src/storage/page/extendible_htable_directory_page.cpp"
"src/include/storage/page/extendible_htable_header_page.h"
"src/storage/page/extendible_htable_header_page.cpp"
"src/include/container/disk/hash/disk_extendible_hash_table.h"
"src/container/disk/hash/disk_extendible_hash_table.cpp"
"src/include/storage/page/b_plus_tree_page.h"
"src/storage/page/b_plus_tree_page.cpp"
"src/include/storage/page/b_plus_tree_internal_page.h"
"src/storage/page/b_plus_tree_internal_page.cpp"
"src/include/storage/page/b_plus_tree_leaf_page.h"
"src/storage/page/b_plus_tree_leaf_page.cpp"
"src/include/storage/index/index_iterator.h"
"src/storage/index/index_iterator.cpp"
"src/include/storage/index/b_plus_tree.h"
"src/include/storage/index/b_plus_tree_debug.h"
"src/storage/index/b_plus_tree.cpp"
${P1_FILES}
)
add_custom_target(check-clang-tidy-p2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
// Identification: src/container/disk/hash/disk_extendible_hash_table_utils.cpp
//
// Copyright (c) 2015-2023, Carnegie Mellon University Database Group
// Copyright (c) 2015-2024, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

Expand Down
17 changes: 8 additions & 9 deletions src/include/storage/index/b_plus_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

#include "common/config.h"
#include "common/macros.h"
#include "concurrency/transaction.h"
#include "storage/index/index_iterator.h"
#include "storage/page/b_plus_tree_header_page.h"
#include "storage/page/b_plus_tree_internal_page.h"
Expand Down Expand Up @@ -67,20 +66,20 @@ class BPlusTree {

public:
explicit BPlusTree(std::string name, page_id_t header_page_id, BufferPoolManager *buffer_pool_manager,
const KeyComparator &comparator, int leaf_max_size = LEAF_PAGE_SIZE,
int internal_max_size = INTERNAL_PAGE_SIZE);
const KeyComparator &comparator, int leaf_max_size = LEAF_PAGE_SLOT_CNT,
int internal_max_size = INTERNAL_PAGE_SLOT_CNT);

// Returns true if this B+ tree has no keys and values.
auto IsEmpty() const -> bool;

// Insert a key-value pair into this B+ tree.
auto Insert(const KeyType &key, const ValueType &value, Transaction *txn = nullptr) -> bool;
auto Insert(const KeyType &key, const ValueType &value) -> bool;

// Remove a key and its value from this B+ tree.
void Remove(const KeyType &key, Transaction *txn);
void Remove(const KeyType &key);

// Return the value associated with a given key
auto GetValue(const KeyType &key, std::vector<ValueType> *result, Transaction *txn = nullptr) -> bool;
auto GetValue(const KeyType &key, std::vector<ValueType> *result) -> bool;

// Return the page id of the root node
auto GetRootPageId() -> page_id_t;
Expand Down Expand Up @@ -112,10 +111,10 @@ class BPlusTree {
auto DrawBPlusTree() -> std::string;

// read data from file and insert one by one
void InsertFromFile(const std::filesystem::path &file_name, Transaction *txn = nullptr);
void InsertFromFile(const std::filesystem::path &file_name);

// read data from file and remove one by one
void RemoveFromFile(const std::filesystem::path &file_name, Transaction *txn = nullptr);
void RemoveFromFile(const std::filesystem::path &file_name);

/**
* @brief Read batch operations from input file, below is a sample file format
Expand All @@ -126,7 +125,7 @@ class BPlusTree {
* (3) (7)
* (1,2) (3,4) (5,6) (7,10,30) // The output tree example
*/
void BatchOpsFromFile(const std::filesystem::path &file_name, Transaction *txn = nullptr);
void BatchOpsFromFile(const std::filesystem::path &file_name);

private:
/* Debug Routines for FREE!! */
Expand Down
278 changes: 278 additions & 0 deletions src/include/storage/index/b_plus_tree_debug.h
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
3 changes: 2 additions & 1 deletion src/include/storage/index/index_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* For range scan of b+ tree
*/
#pragma once
#include <utility>
#include "storage/page/b_plus_tree_leaf_page.h"

namespace bustub {
Expand All @@ -28,7 +29,7 @@ class IndexIterator {

auto IsEnd() -> bool;

auto operator*() -> const MappingType &;
auto operator*() -> std::pair<const KeyType &, const ValueType &>;

auto operator++() -> IndexIterator &;

Expand Down
Loading

0 comments on commit c4f96a1

Please sign in to comment.