From d47e32e98613bc7903fa65de70b0bcecd53cf95b Mon Sep 17 00:00:00 2001 From: happyZYM Date: Fri, 26 Apr 2024 08:50:11 +0000 Subject: [PATCH] buffer pool manager passed Memory River Test --- bpt/include/bpt/bpt_page.hpp | 16 +++-- bpt/include/bpt/buffer_pool_manager.h | 4 ++ bpt/include/bpt/disk_manager.h | 2 +- bpt/src/buffer_pool_manager.cpp | 5 +- bpt/src/disk_manager.cpp | 3 + test/MemoryRiver.hpp | 98 +++++++++++++++++++++++++++ test/buffer_pool_manager_test.cpp | 62 +++++++++++++++++ 7 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 test/MemoryRiver.hpp diff --git a/bpt/include/bpt/bpt_page.hpp b/bpt/include/bpt/bpt_page.hpp index e5fb462..c2f7b29 100644 --- a/bpt/include/bpt/bpt_page.hpp +++ b/bpt/include/bpt/bpt_page.hpp @@ -2,9 +2,8 @@ #define BPT_PAGE_HPP #include #include "bpt/config.h" -#pragma pack(push, 1) template -class BPlusTreePage { +struct ActualDataType { typedef std::pair value_type; page_id_t p_n; page_id_t p_parent; @@ -13,8 +12,15 @@ class BPlusTreePage { const static size_t kMaxKeyCount = (kPageSize - sizeof(page_id_t) * 2 - sizeof(uint8_t) - sizeof(uint16_t)) / sizeof(value_type); value_type p_data[kMaxKeyCount]; - char filler[kPageSize - sizeof(page_id_t) * 2 - sizeof(uint8_t) - sizeof(uint16_t) - - sizeof(value_type) * kMaxKeyCount]; }; -#pragma pack(pop) +template +union BPlusTreePage { + inline BPlusTreePage() {} + inline BPlusTreePage &operator=(const BPlusTreePage &that) { + memcpy(this, &that, sizeof(BPlusTreePage)); + return *this; + } + ActualDataType data; + char filler[kPageSize]; +}; #endif // BPT_PAGE_H \ No newline at end of file diff --git a/bpt/include/bpt/buffer_pool_manager.h b/bpt/include/bpt/buffer_pool_manager.h index 077b569..62e53b3 100644 --- a/bpt/include/bpt/buffer_pool_manager.h +++ b/bpt/include/bpt/buffer_pool_manager.h @@ -362,6 +362,10 @@ class BufferPoolManager { /** * @brief Flush all the pages in the buffer pool to disk. + * + * @warning The buffer pool manager will automatically call FlushAllPages before being destroyed, but if the disk + * manager is closed, it will do nothing. And Page Guard should be destroyed before Buffer Pool Manager, Buffer Pool + * Manager should be destroyed before Disk Manager. */ void FlushAllPages(); diff --git a/bpt/include/bpt/disk_manager.h b/bpt/include/bpt/disk_manager.h index e7ef391..744d2e5 100644 --- a/bpt/include/bpt/disk_manager.h +++ b/bpt/include/bpt/disk_manager.h @@ -2,7 +2,7 @@ #define DISK_MANAGER_H #include #include -#include "config.h" +#include "bpt/config.h" class DiskManager { /** * The Data Structure on Disk: diff --git a/bpt/src/buffer_pool_manager.cpp b/bpt/src/buffer_pool_manager.cpp index 544d470..b4c6c3c 100644 --- a/bpt/src/buffer_pool_manager.cpp +++ b/bpt/src/buffer_pool_manager.cpp @@ -97,7 +97,10 @@ BufferPoolManager::BufferPoolManager(size_t pool_size, size_t replacer_k, DiskMa free_list_.emplace_back(static_cast(i)); } } -BufferPoolManager::~BufferPoolManager() { delete[] pages_; } +BufferPoolManager::~BufferPoolManager() { + FlushAllPages(); + delete[] pages_; +} page_id_t BufferPoolManager::AllocatePage() { page_id_t page_id = disk_manager->AllocNewEmptyPageId(); diff --git a/bpt/src/disk_manager.cpp b/bpt/src/disk_manager.cpp index 3b6af91..2c8ea5b 100644 --- a/bpt/src/disk_manager.cpp +++ b/bpt/src/disk_manager.cpp @@ -46,6 +46,7 @@ char *DiskManager::RawDataMemory() { return raw_data_memory; } size_t DiskManager::RawDatMemorySize() { return kPageSize - meta_data_size; } void DiskManager::FullyFlush() { + if(fp==nullptr) return; fseek(fp, 0, SEEK_SET); fwrite(&first_empty_page_id, sizeof(page_id_t), 1, fp); fwrite(¤t_total_page_count, sizeof(size_t), 1, fp); @@ -63,11 +64,13 @@ void DiskManager::Close() { } void DiskManager::ReadPage(page_id_t page_id, char *page_data_ptr) { + if (fp == nullptr) return; fseek(fp, page_id * kPageSize, SEEK_SET); fread(page_data_ptr, kPageSize, 1, fp); } void DiskManager::WritePage(page_id_t page_id, const char *page_data_ptr) { + if (fp == nullptr) return; fseek(fp, page_id * kPageSize, SEEK_SET); fwrite(page_data_ptr, kPageSize, 1, fp); } diff --git a/test/MemoryRiver.hpp b/test/MemoryRiver.hpp new file mode 100644 index 0000000..85c1a8a --- /dev/null +++ b/test/MemoryRiver.hpp @@ -0,0 +1,98 @@ +#include +#include +#include "bpt/buffer_pool_manager.h" +#include "bpt/config.h" +#include "bpt/disk_manager.h" +#ifndef BPT_MEMORYRIVER_HPP +#define BPT_MEMORYRIVER_HPP + +#include + +using std::fstream; +using std::ifstream; +using std::ofstream; +using std::string; + +template +class MemoryRiver { + private: + union Page { + T data; + char filler[4096]; + }; + std::string file_name; + DiskManager *disk_manager; + BufferPoolManager *bpm; + char *raw_mem; + static_assert(info_len * sizeof(int) <= 4000, "info_len should be less than 4000"); + static_assert(sizeof(T) <= 4096, "T should be less than 4096"); + + public: + MemoryRiver() : disk_manager(nullptr), bpm(nullptr), file_name("") {} + + MemoryRiver(const string &file_name) : file_name(file_name) { + disk_manager = new DiskManager(file_name); + bpm = new BufferPoolManager(100, 5, disk_manager); + raw_mem = bpm->RawDataMemory(); + } + void CloseFile() { + bpm->FlushAllPages(); + file_name = ""; + delete bpm; + bpm = nullptr; + delete disk_manager; + disk_manager = nullptr; + } + ~MemoryRiver() { + if (file_name != "") CloseFile(); + } + + void initialise(string FN = "") { + if (file_name != "") { + std::string name_bak=file_name; + CloseFile(); + file_name = name_bak; + } + if (FN != "") file_name = FN; + if (file_name == "") return; + disk_manager = new DiskManager(file_name); + bpm = new BufferPoolManager(100, 5, disk_manager); + raw_mem = bpm->RawDataMemory(); + memset(raw_mem, 0, bpm->RawDatMemorySize()); + } + + void get_info(int &tmp, int n) { + if (n > info_len) return; + n--; + memcpy(&tmp, raw_mem + n * sizeof(int), sizeof(int)); + } + + void write_info(int tmp, int n) { + if (n > info_len) return; + n--; + memcpy(raw_mem + n * sizeof(int), &tmp, sizeof(int)); + } + + int write(T &t) { + frame_id_t frame_id; + BasicPageGuard guard = bpm->NewPageGuarded(&frame_id); + guard.AsMut()->data = t; + return frame_id; + } + + void update(T &t, const int index) { + WritePageGuard guard = bpm->FetchPageWrite(index); + guard.AsMut()->data = t; + } + + //读出位置索引index对应的T对象的值并赋值给t,保证调用的index都是由write函数产生 + void read(T &t, const int index) { + ReadPageGuard guard = bpm->FetchPageRead(index); + t = guard.As()->data; + } + + //删除位置索引index对应的对象(不涉及空间回收时,可忽略此函数),保证调用的index都是由write函数产生 + void Delete(int index) { bpm->DeletePage(index); } +}; + +#endif // BPT_MEMORYRIVER_HPP \ No newline at end of file diff --git a/test/buffer_pool_manager_test.cpp b/test/buffer_pool_manager_test.cpp index 15b3a89..fd836f4 100644 --- a/test/buffer_pool_manager_test.cpp +++ b/test/buffer_pool_manager_test.cpp @@ -5,7 +5,10 @@ #include #include #include +#include "bpt/bpt_page.hpp" #include "bpt/config.h" +#include "bpt/disk_manager.h" +#include "MemoryRiver.hpp" // Demonstrate some basic assertions. TEST(HelloTest, BasicAssertions) { // Expect two strings not to be equal. @@ -139,4 +142,63 @@ TEST(BufferPoolManagerTest, SampleTest) { delete bpm; delete disk_manager; +} + +TEST(StoreTest, Test1) { + remove("/tmp/test.db"); + DiskManager *disk_manager_ptr = new DiskManager("/tmp/test.db"); + BufferPoolManager *buffer_pool_manager = new BufferPoolManager(10, 3, disk_manager_ptr); + char *mem = buffer_pool_manager->RawDataMemory(); + uint32_t a = 0x1f2f3f4f; + memcpy(mem, &a, sizeof(uint32_t)); + delete buffer_pool_manager; + delete disk_manager_ptr; + disk_manager_ptr = new DiskManager("/tmp/test.db"); + buffer_pool_manager = new BufferPoolManager(10, 3, disk_manager_ptr); + mem = buffer_pool_manager->RawDataMemory(); + uint32_t b; + memcpy(&b, mem, sizeof(uint32_t)); + EXPECT_EQ(a, b); + delete buffer_pool_manager; + delete disk_manager_ptr; + disk_manager_ptr = new DiskManager("/tmp/test.db"); + buffer_pool_manager = new BufferPoolManager(10, 3, disk_manager_ptr); + page_id_t page_id; + auto basic_guard = buffer_pool_manager->NewPageGuarded(&page_id); + typedef BPlusTreePage PageType; + PageType c; + c.data.p_n = 0x1f2f3f4f; + c.data.key_count = 0x1f2a; + c.data.is_leaf = 0x3e; + c.data.p_data[17].first = 0x8f7f6f5f4f3f2f1f; + c.filler[0] = 0x1f; + *basic_guard.AsMut() = c; + basic_guard.Drop(); + auto read_guard = buffer_pool_manager->FetchPageRead(page_id); + EXPECT_EQ(c.data.p_n, read_guard.As()->data.p_n); + EXPECT_EQ(0, memcmp(&c, read_guard.As(), sizeof(PageType))); + read_guard.Drop(); + delete buffer_pool_manager; + delete disk_manager_ptr; + disk_manager_ptr = new DiskManager("/tmp/test.db"); + buffer_pool_manager = new BufferPoolManager(10, 3, disk_manager_ptr); + read_guard = buffer_pool_manager->FetchPageRead(page_id); + EXPECT_EQ(c.data.p_n, read_guard.As()->data.p_n); + EXPECT_EQ(0, memcmp(&c, read_guard.As(), sizeof(PageType))); + read_guard.Drop(); + delete buffer_pool_manager; + delete disk_manager_ptr; +} + +TEST(MemoryRiver,T1) { + MemoryRiver river; + river.initialise("/tmp/test2.db"); + int x=3; + river.write_info(x,1); + unsigned long long dat1=0x1f2f3f4f5f6f7f8f; + frame_id_t frame_id = river.write(dat1); + for(int i=0;i<100;i++) { + dat1++; + river.write(dat1); + } } \ No newline at end of file