Skip to content

Commit

Permalink
test(sqllogictest): add test utils regarding bpm & disk (#764)
Browse files Browse the repository at this point in the history
Introduce necessary test utils for checking students' external merge sort implementations, including:
1. Maximum number of pages written to disk
2. Minimum number of pages written to disk
3. Minimum number of pages deleted on disk
  • Loading branch information
xx01cyx authored Oct 21, 2024
1 parent 32d7085 commit 719e735
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 24 deletions.
10 changes: 10 additions & 0 deletions src/include/storage/disk/disk_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class DiskManager {
*/
virtual void ReadPage(page_id_t page_id, char *page_data);

/**
* Delete a page from the database file. Reclaim the disk space.
* @param page_id id of the page
*/
virtual void DeletePage(page_id_t page_id);

/**
* Flush the entire log buffer into disk.
* @param log_data raw log data
Expand All @@ -93,6 +99,9 @@ class DiskManager {
/** @return the number of disk writes */
auto GetNumWrites() const -> int;

/** @return the number of deletions */
auto GetNumDeletes() const -> int;

/**
* Sets the future which is used to check for non-blocking flushes.
* @param f the non-blocking flush check
Expand All @@ -115,6 +124,7 @@ class DiskManager {
std::filesystem::path file_name_;
int num_flushes_{0};
int num_writes_{0};
int num_deletes_{0};
bool flush_log_{false};
std::future<void> *flush_log_f_{nullptr};
// With multiple buffer pool instances, need to protect file access
Expand Down
9 changes: 9 additions & 0 deletions src/include/storage/disk/disk_manager_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class DiskManagerUnlimitedMemory : public DiskManager {
l.unlock();

memcpy(ptr->first.data(), page_data, BUSTUB_PAGE_SIZE);
num_writes_ += 1;

PostProcessLatency(page_id);
}
Expand Down Expand Up @@ -158,6 +159,14 @@ class DiskManagerUnlimitedMemory : public DiskManager {
PostProcessLatency(page_id);
}

/**
* Delete a page from the database file. Reclaim the disk space.
* Note: This is a no-op for now without a more complex data structure to
* track deallocated pages.
* @param page_id id of the page
*/
void DeletePage(page_id_t page_id) override { num_deletes_ += 1; }

void ProcessLatency(page_id_t page_id) {
uint64_t sleep_micro_sec = 1000; // for random access, 1ms latency
if (latency_simulator_enabled_) {
Expand Down
2 changes: 1 addition & 1 deletion src/include/storage/disk/disk_scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class DiskScheduler {
*
* @param page_id The page ID of the page to deallocate from disk.
*/
void DeallocatePage(page_id_t page_id) {}
void DeallocatePage(page_id_t page_id) { disk_manager_->DeletePage(page_id); }

private:
/** Pointer to the disk manager. */
Expand Down
15 changes: 13 additions & 2 deletions src/storage/disk/disk_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ void DiskManager::ReadPage(page_id_t page_id, char *page_data) {
}
}

/**
* Note: This is a no-op for now without a more complex data structure to
* track deallocated pages.
*/
void DiskManager::DeletePage(page_id_t page_id) { num_deletes_ += 1; }

/**
* Write the contents of the log into disk file
* Only return when sync is done, and only perform sequence write
Expand Down Expand Up @@ -215,15 +221,20 @@ auto DiskManager::ReadLog(char *log_data, int size, int offset) -> bool {
*/
auto DiskManager::GetNumFlushes() const -> int { return num_flushes_; }

/**
* Returns true if the log is currently being flushed
*/
auto DiskManager::GetFlushState() const -> bool { return flush_log_; }

/**
* Returns number of Writes made so far
*/
auto DiskManager::GetNumWrites() const -> int { return num_writes_; }

/**
* Returns true if the log is currently being flushed
* Returns number of deletions made so far
*/
auto DiskManager::GetFlushState() const -> bool { return flush_log_; }
auto DiskManager::GetNumDeletes() const -> int { return num_deletes_; }

/**
* Private helper function to get disk file size
Expand Down
80 changes: 59 additions & 21 deletions tools/sqllogictest/sqllogictest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "argparse/argparse.hpp"
#include "common/bustub_instance.h"
#include "common/config.h"
#include "common/exception.h"
#include "common/util/string_util.h"
#include "execution/check_options.h"
Expand Down Expand Up @@ -137,30 +138,30 @@ auto ProcessExtraOptions(const std::string &sql, bustub::BusTubInstance &instanc
auto expected_cols_proj = std::stoi(args[2]);
auto expected_cols_agg = std::stoi(args[3]);
// find agg & proj plan and test if the output schema has the expected number of columns
auto lines = bustub::StringUtil::Split(result.str(), "\n");
for (auto &line : lines) {
bustub::StringUtil::LTrim(&line);
if (bustub::StringUtil::StartsWith(line, "Agg")) {
auto cols = bustub::StringUtil::Split(line, "],");
if (cols.size() != 3) {
fmt::print("Agg plan wrong formatting!\n");
return false;
}
for (int i = 0; i < 2; i++) {
if (bustub::StringUtil::Count(cols[i], "\",")+1 > static_cast<size_t>(expected_cols_agg)) {
fmt::print("Agg wrong column pruning count!\n");
return false;
}
}
break;
auto lines = bustub::StringUtil::Split(result.str(), "\n");
for (auto &line : lines) {
bustub::StringUtil::LTrim(&line);
if (bustub::StringUtil::StartsWith(line, "Agg")) {
auto cols = bustub::StringUtil::Split(line, "],");
if (cols.size() != 3) {
fmt::print("Agg plan wrong formatting!\n");
return false;
}
if (bustub::StringUtil::StartsWith(line, "Projection")) {
if (bustub::StringUtil::Count(line, "\",")+1 > static_cast<size_t>(expected_cols_proj)) {
fmt::print("Projection wrong column pruning count!\n");
for (int i = 0; i < 2; i++) {
if (bustub::StringUtil::Count(cols[i], "\",") + 1 > static_cast<size_t>(expected_cols_agg)) {
fmt::print("Agg wrong column pruning count!\n");
return false;
}
}
break;
}
if (bustub::StringUtil::StartsWith(line, "Projection")) {
if (bustub::StringUtil::Count(line, "\",") + 1 > static_cast<size_t>(expected_cols_proj)) {
fmt::print("Projection wrong column pruning count!\n");
return false;
}
}
}
} else {
throw bustub::NotImplementedException(fmt::format("unsupported extra option: {}", opt));
}
Expand Down Expand Up @@ -224,6 +225,15 @@ auto main(int argc, char **argv) -> int { // NOLINT
program.add_argument("--verbose").help("increase output verbosity").default_value(false).implicit_value(true);
program.add_argument("-d", "--diff").help("write diff file").default_value(false).implicit_value(true);
program.add_argument("--in-memory").help("use in-memory backend").default_value(false).implicit_value(true);
program.add_argument("--bpm-size")
.help("size of the buffer pool")
.default_value(std::to_string(bustub::BUFFER_POOL_SIZE));
program.add_argument("--check-min-disk-write")
.help("the minimum disk write threshold to be checked at the end of the program");
program.add_argument("--check-max-disk-write")
.help("the maximum disk write threshold to be checked at the end of the program");
program.add_argument("--check-min-disk-delete")
.help("the maximum disk deletion threshold to be checked at the end of the program");

try {
program.parse_args(argc, argv);
Expand All @@ -235,6 +245,8 @@ auto main(int argc, char **argv) -> int { // NOLINT

bool verbose = program.get<bool>("verbose");
bool diff = program.get<bool>("diff");
auto check_min_disk_write = program.present("check-min-disk-write");

std::string filename = program.get<std::string>("file");
std::ifstream t(filename);

Expand All @@ -253,11 +265,12 @@ auto main(int argc, char **argv) -> int { // NOLINT
}

std::unique_ptr<bustub::BusTubInstance> bustub;
size_t bpm_size = std::stoul(program.get<std::string>("bpm-size"));

if (program.get<bool>("--in-memory")) {
bustub = std::make_unique<bustub::BusTubInstance>();
bustub = std::make_unique<bustub::BusTubInstance>(bpm_size);
} else {
bustub = std::make_unique<bustub::BusTubInstance>("test.bustub");
bustub = std::make_unique<bustub::BusTubInstance>("test.bustub", bpm_size);
}

bustub->GenerateMockTable();
Expand Down Expand Up @@ -365,5 +378,30 @@ auto main(int argc, char **argv) -> int { // NOLINT
}
}

if (program.is_used("--check-min-disk-write")) {
int min_disk_write_num = std::stoi(program.get("--check-min-disk-write"));
int actual_disk_write_num = bustub->disk_manager_->GetNumWrites();
if (actual_disk_write_num < min_disk_write_num) {
fmt::print("test incurred {} times of disk write, which is too low\n", actual_disk_write_num);
return 1;
}
}
if (program.is_used("--check-max-disk-write")) {
int max_disk_write_num = std::stoi(program.get("--check-max-disk-write"));
int actual_disk_write_num = bustub->disk_manager_->GetNumWrites();
if (actual_disk_write_num > max_disk_write_num) {
fmt::print("test incurred {} times of disk write, which is too high\n", actual_disk_write_num);
return 1;
}
}
if (program.is_used("--check-min-disk-delete")) {
int min_disk_delete_num = std::stoi(program.get("--check-min-disk-delete"));
int actual_disk_delete_num = bustub->disk_manager_->GetNumDeletes();
if (actual_disk_delete_num < min_disk_delete_num) {
fmt::print("test incurred {} times of disk deletion, which is too low\n", actual_disk_delete_num);
return 1;
}
}

return 0;
}

0 comments on commit 719e735

Please sign in to comment.