buffer pool manager passed Memory River Test

This commit is contained in:
2024-04-26 08:50:11 +00:00
parent 8e1d8c7291
commit d47e32e986
7 changed files with 183 additions and 7 deletions

View File

@ -2,9 +2,8 @@
#define BPT_PAGE_HPP #define BPT_PAGE_HPP
#include <utility> #include <utility>
#include "bpt/config.h" #include "bpt/config.h"
#pragma pack(push, 1)
template <typename KeyType, size_t kPageSize = 4096> template <typename KeyType, size_t kPageSize = 4096>
class BPlusTreePage { struct ActualDataType {
typedef std::pair<KeyType, default_numeric_index_t> value_type; typedef std::pair<KeyType, default_numeric_index_t> value_type;
page_id_t p_n; page_id_t p_n;
page_id_t p_parent; page_id_t p_parent;
@ -13,8 +12,15 @@ class BPlusTreePage {
const static size_t kMaxKeyCount = const static size_t kMaxKeyCount =
(kPageSize - sizeof(page_id_t) * 2 - sizeof(uint8_t) - sizeof(uint16_t)) / sizeof(value_type); (kPageSize - sizeof(page_id_t) * 2 - sizeof(uint8_t) - sizeof(uint16_t)) / sizeof(value_type);
value_type p_data[kMaxKeyCount]; 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 <typename KeyType, size_t kPageSize = 4096>
union BPlusTreePage {
inline BPlusTreePage() {}
inline BPlusTreePage &operator=(const BPlusTreePage &that) {
memcpy(this, &that, sizeof(BPlusTreePage));
return *this;
}
ActualDataType<KeyType, kPageSize> data;
char filler[kPageSize];
};
#endif // BPT_PAGE_H #endif // BPT_PAGE_H

View File

@ -362,6 +362,10 @@ class BufferPoolManager {
/** /**
* @brief Flush all the pages in the buffer pool to disk. * @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(); void FlushAllPages();

View File

@ -2,7 +2,7 @@
#define DISK_MANAGER_H #define DISK_MANAGER_H
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "config.h" #include "bpt/config.h"
class DiskManager { class DiskManager {
/** /**
* The Data Structure on Disk: * The Data Structure on Disk:

View File

@ -97,7 +97,10 @@ BufferPoolManager::BufferPoolManager(size_t pool_size, size_t replacer_k, DiskMa
free_list_.emplace_back(static_cast<int>(i)); free_list_.emplace_back(static_cast<int>(i));
} }
} }
BufferPoolManager::~BufferPoolManager() { delete[] pages_; } BufferPoolManager::~BufferPoolManager() {
FlushAllPages();
delete[] pages_;
}
page_id_t BufferPoolManager::AllocatePage() { page_id_t BufferPoolManager::AllocatePage() {
page_id_t page_id = disk_manager->AllocNewEmptyPageId(); page_id_t page_id = disk_manager->AllocNewEmptyPageId();

View File

@ -46,6 +46,7 @@ char *DiskManager::RawDataMemory() { return raw_data_memory; }
size_t DiskManager::RawDatMemorySize() { return kPageSize - meta_data_size; } size_t DiskManager::RawDatMemorySize() { return kPageSize - meta_data_size; }
void DiskManager::FullyFlush() { void DiskManager::FullyFlush() {
if(fp==nullptr) return;
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
fwrite(&first_empty_page_id, sizeof(page_id_t), 1, fp); fwrite(&first_empty_page_id, sizeof(page_id_t), 1, fp);
fwrite(&current_total_page_count, sizeof(size_t), 1, fp); fwrite(&current_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) { void DiskManager::ReadPage(page_id_t page_id, char *page_data_ptr) {
if (fp == nullptr) return;
fseek(fp, page_id * kPageSize, SEEK_SET); fseek(fp, page_id * kPageSize, SEEK_SET);
fread(page_data_ptr, kPageSize, 1, fp); fread(page_data_ptr, kPageSize, 1, fp);
} }
void DiskManager::WritePage(page_id_t page_id, const char *page_data_ptr) { void DiskManager::WritePage(page_id_t page_id, const char *page_data_ptr) {
if (fp == nullptr) return;
fseek(fp, page_id * kPageSize, SEEK_SET); fseek(fp, page_id * kPageSize, SEEK_SET);
fwrite(page_data_ptr, kPageSize, 1, fp); fwrite(page_data_ptr, kPageSize, 1, fp);
} }

98
test/MemoryRiver.hpp Normal file
View File

@ -0,0 +1,98 @@
#include <cstddef>
#include <cstring>
#include "bpt/buffer_pool_manager.h"
#include "bpt/config.h"
#include "bpt/disk_manager.h"
#ifndef BPT_MEMORYRIVER_HPP
#define BPT_MEMORYRIVER_HPP
#include <fstream>
using std::fstream;
using std::ifstream;
using std::ofstream;
using std::string;
template <class T, int info_len = 2>
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<Page>()->data = t;
return frame_id;
}
void update(T &t, const int index) {
WritePageGuard guard = bpm->FetchPageWrite(index);
guard.AsMut<Page>()->data = t;
}
//读出位置索引index对应的T对象的值并赋值给t保证调用的index都是由write函数产生
void read(T &t, const int index) {
ReadPageGuard guard = bpm->FetchPageRead(index);
t = guard.As<Page>()->data;
}
//删除位置索引index对应的对象(不涉及空间回收时,可忽略此函数)保证调用的index都是由write函数产生
void Delete(int index) { bpm->DeletePage(index); }
};
#endif // BPT_MEMORYRIVER_HPP

View File

@ -5,7 +5,10 @@
#include <memory> #include <memory>
#include <random> #include <random>
#include <string> #include <string>
#include "bpt/bpt_page.hpp"
#include "bpt/config.h" #include "bpt/config.h"
#include "bpt/disk_manager.h"
#include "MemoryRiver.hpp"
// Demonstrate some basic assertions. // Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) { TEST(HelloTest, BasicAssertions) {
// Expect two strings not to be equal. // Expect two strings not to be equal.
@ -140,3 +143,62 @@ TEST(BufferPoolManagerTest, SampleTest) {
delete bpm; delete bpm;
delete disk_manager; 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<unsigned long long> 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<PageType>() = c;
basic_guard.Drop();
auto read_guard = buffer_pool_manager->FetchPageRead(page_id);
EXPECT_EQ(c.data.p_n, read_guard.As<PageType>()->data.p_n);
EXPECT_EQ(0, memcmp(&c, read_guard.As<PageType>(), 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<PageType>()->data.p_n);
EXPECT_EQ(0, memcmp(&c, read_guard.As<PageType>(), sizeof(PageType)));
read_guard.Drop();
delete buffer_pool_manager;
delete disk_manager_ptr;
}
TEST(MemoryRiver,T1) {
MemoryRiver<unsigned long long> 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);
}
}