fully passed entire test
This commit is contained in:
@ -16,16 +16,27 @@ using std::string;
|
|||||||
template <class T, int info_len = 2>
|
template <class T, int info_len = 2>
|
||||||
class MemoryRiver {
|
class MemoryRiver {
|
||||||
private:
|
private:
|
||||||
union Page {
|
struct ElementPair {
|
||||||
T data;
|
T data;
|
||||||
|
size_t nxt_blank;
|
||||||
|
};
|
||||||
|
const static size_t max_element_in_page = (4096 - sizeof(size_t)) / sizeof(ElementPair);
|
||||||
|
struct DataType {
|
||||||
|
size_t elements_count;
|
||||||
|
ElementPair elements[max_element_in_page];
|
||||||
|
};
|
||||||
|
union Page {
|
||||||
|
DataType dat;
|
||||||
char filler[4096];
|
char filler[4096];
|
||||||
};
|
};
|
||||||
|
// data_id = frame_id * max_element_in_page + element_id
|
||||||
std::string file_name;
|
std::string file_name;
|
||||||
DiskManager *disk_manager;
|
DiskManager *disk_manager;
|
||||||
BufferPoolManager *bpm;
|
BufferPoolManager *bpm;
|
||||||
|
size_t first_blank_element_pair_id;
|
||||||
char *raw_mem;
|
char *raw_mem;
|
||||||
static_assert(info_len * sizeof(int) <= 4000, "info_len should be less than 4000");
|
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");
|
static_assert(sizeof(T) <= 4088, "T should be less than 4088");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryRiver() : disk_manager(nullptr), bpm(nullptr), file_name("") {}
|
MemoryRiver() : disk_manager(nullptr), bpm(nullptr), file_name("") {}
|
||||||
@ -34,8 +45,10 @@ class MemoryRiver {
|
|||||||
disk_manager = new DiskManager(file_name);
|
disk_manager = new DiskManager(file_name);
|
||||||
bpm = new BufferPoolManager(100, 5, disk_manager);
|
bpm = new BufferPoolManager(100, 5, disk_manager);
|
||||||
raw_mem = bpm->RawDataMemory();
|
raw_mem = bpm->RawDataMemory();
|
||||||
|
memcpy(&first_blank_element_pair_id, raw_mem, sizeof(size_t));
|
||||||
}
|
}
|
||||||
void CloseFile() {
|
void CloseFile() {
|
||||||
|
memcpy(raw_mem, &first_blank_element_pair_id, sizeof(size_t));
|
||||||
bpm->FlushAllPages();
|
bpm->FlushAllPages();
|
||||||
file_name = "";
|
file_name = "";
|
||||||
delete bpm;
|
delete bpm;
|
||||||
@ -49,7 +62,7 @@ class MemoryRiver {
|
|||||||
|
|
||||||
void initialise(string FN = "") {
|
void initialise(string FN = "") {
|
||||||
if (file_name != "") {
|
if (file_name != "") {
|
||||||
std::string name_bak=file_name;
|
std::string name_bak = file_name;
|
||||||
CloseFile();
|
CloseFile();
|
||||||
file_name = name_bak;
|
file_name = name_bak;
|
||||||
}
|
}
|
||||||
@ -59,40 +72,74 @@ class MemoryRiver {
|
|||||||
bpm = new BufferPoolManager(100, 5, disk_manager);
|
bpm = new BufferPoolManager(100, 5, disk_manager);
|
||||||
raw_mem = bpm->RawDataMemory();
|
raw_mem = bpm->RawDataMemory();
|
||||||
memset(raw_mem, 0, bpm->RawDatMemorySize());
|
memset(raw_mem, 0, bpm->RawDatMemorySize());
|
||||||
|
first_blank_element_pair_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_info(int &tmp, int n) {
|
void get_info(int &tmp, int n) {
|
||||||
if (n > info_len) return;
|
if (n > info_len) return;
|
||||||
n--;
|
n += 2;
|
||||||
memcpy(&tmp, raw_mem + n * sizeof(int), sizeof(int));
|
memcpy(&tmp, raw_mem + n * sizeof(int), sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_info(int tmp, int n) {
|
void write_info(int tmp, int n) {
|
||||||
if (n > info_len) return;
|
if (n > info_len) return;
|
||||||
n--;
|
n += 2;
|
||||||
memcpy(raw_mem + n * sizeof(int), &tmp, sizeof(int));
|
memcpy(raw_mem + n * sizeof(int), &tmp, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
int write(T &t) {
|
int write(T &t) {
|
||||||
frame_id_t frame_id;
|
size_t element_id = first_blank_element_pair_id;
|
||||||
BasicPageGuard guard = bpm->NewPageGuarded(&frame_id);
|
size_t res_id = 0;
|
||||||
guard.AsMut<Page>()->data = t;
|
if (element_id != 0) {
|
||||||
return frame_id;
|
res_id = element_id;
|
||||||
|
frame_id_t frame_id = element_id / max_element_in_page;
|
||||||
|
element_id %= max_element_in_page;
|
||||||
|
WritePageGuard guard = bpm->FetchPageWrite(frame_id);
|
||||||
|
first_blank_element_pair_id = guard.AsMut<Page>()->dat.elements[element_id].nxt_blank;
|
||||||
|
guard.AsMut<Page>()->dat.elements[element_id].data = t;
|
||||||
|
guard.AsMut<Page>()->dat.elements_count++;
|
||||||
|
} else {
|
||||||
|
frame_id_t frame_id;
|
||||||
|
BasicPageGuard guard = bpm->NewPageGuarded(&frame_id);
|
||||||
|
guard.AsMut<Page>()->dat.elements[0].data = t;
|
||||||
|
element_id = frame_id * max_element_in_page;
|
||||||
|
res_id = element_id;
|
||||||
|
if (max_element_in_page > 1) first_blank_element_pair_id = element_id + 1;
|
||||||
|
for (size_t i = 1; i < max_element_in_page - 1; i++) {
|
||||||
|
guard.AsMut<Page>()->dat.elements[i].nxt_blank = element_id + i + 1;
|
||||||
|
}
|
||||||
|
guard.AsMut<Page>()->dat.elements[max_element_in_page - 1].nxt_blank = 0;
|
||||||
|
guard.AsMut<Page>()->dat.elements_count = 1;
|
||||||
|
}
|
||||||
|
return res_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(T &t, const int index) {
|
void update(T &t, const int index) {
|
||||||
WritePageGuard guard = bpm->FetchPageWrite(index);
|
size_t frame_id = index / max_element_in_page;
|
||||||
guard.AsMut<Page>()->data = t;
|
WritePageGuard guard = bpm->FetchPageWrite(frame_id);
|
||||||
|
guard.AsMut<Page>()->dat.elements[index % max_element_in_page].data = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
//读出位置索引index对应的T对象的值并赋值给t,保证调用的index都是由write函数产生
|
//读出位置索引index对应的T对象的值并赋值给t,保证调用的index都是由write函数产生
|
||||||
void read(T &t, const int index) {
|
void read(T &t, const int index) {
|
||||||
ReadPageGuard guard = bpm->FetchPageRead(index);
|
size_t frame_id = index / max_element_in_page;
|
||||||
t = guard.As<Page>()->data;
|
ReadPageGuard guard = bpm->FetchPageRead(frame_id);
|
||||||
|
t = guard.As<Page>()->dat.elements[index % max_element_in_page].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除位置索引index对应的对象(不涉及空间回收时,可忽略此函数),保证调用的index都是由write函数产生
|
//删除位置索引index对应的对象(不涉及空间回收时,可忽略此函数),保证调用的index都是由write函数产生
|
||||||
void Delete(int index) { bpm->DeletePage(index); }
|
void Delete(int index) {
|
||||||
|
size_t frame_id = index / max_element_in_page;
|
||||||
|
WritePageGuard guard = bpm->FetchPageWrite(frame_id);
|
||||||
|
size_t element_id = index % max_element_in_page;
|
||||||
|
guard.AsMut<Page>()->dat.elements[element_id].nxt_blank = first_blank_element_pair_id;
|
||||||
|
first_blank_element_pair_id = index;
|
||||||
|
guard.AsMut<Page>()->dat.elements_count--;
|
||||||
|
if (guard.AsMut<Page>()->dat.elements_count == 0) {
|
||||||
|
guard.Drop();
|
||||||
|
bpm->DeletePage(frame_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BPT_MEMORYRIVER_HPP
|
#endif // BPT_MEMORYRIVER_HPP
|
@ -1,14 +1,16 @@
|
|||||||
#include "bpt/buffer_pool_manager.h"
|
#include "bpt/buffer_pool_manager.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "MemoryRiver.hpp"
|
||||||
#include "bpt/bpt_page.hpp"
|
#include "bpt/bpt_page.hpp"
|
||||||
#include "bpt/config.h"
|
#include "bpt/config.h"
|
||||||
#include "bpt/disk_manager.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.
|
||||||
@ -190,15 +192,26 @@ TEST(StoreTest, Test1) {
|
|||||||
delete disk_manager_ptr;
|
delete disk_manager_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MemoryRiver,T1) {
|
TEST(MemoryRiver, T1) {
|
||||||
MemoryRiver<unsigned long long> river;
|
remove("/tmp/test2.db");
|
||||||
|
typedef unsigned long long DataType;
|
||||||
|
MemoryRiver<DataType> river;
|
||||||
river.initialise("/tmp/test2.db");
|
river.initialise("/tmp/test2.db");
|
||||||
int x=3;
|
int x = 3;
|
||||||
river.write_info(x,1);
|
river.write_info(x, 1);
|
||||||
unsigned long long dat1=0x1f2f3f4f5f6f7f8f;
|
DataType dat1 = 0x1f2f3f4f5f6f7f8f;
|
||||||
frame_id_t frame_id = river.write(dat1);
|
std::vector<DataType> record;
|
||||||
for(int i=0;i<100;i++) {
|
std::vector<size_t> id_record;
|
||||||
dat1++;
|
int test_cnt = 3;
|
||||||
river.write(dat1);
|
for (int i = 0; i < test_cnt; i++) {
|
||||||
|
DataType tmp = dat1 + i;
|
||||||
|
size_t element_id = river.write(tmp);
|
||||||
|
record.push_back(tmp);
|
||||||
|
id_record.push_back(element_id);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < test_cnt; i++) {
|
||||||
|
DataType tmp;
|
||||||
|
river.read(tmp, id_record[i]);
|
||||||
|
EXPECT_EQ(record[i], tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user