buffer pool manager passed Memory River Test
This commit is contained in:
@ -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
|
@ -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();
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
@ -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();
|
||||||
|
@ -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(¤t_total_page_count, sizeof(size_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) {
|
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
98
test/MemoryRiver.hpp
Normal 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
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user