未验证 提交 10c78caf 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

重构buffer pool (#33)

重构disk buffer pool:
新增BufferPoolManager,管理所有的DiskBufferPool;
原有DiskBufferPool只处理一个文件,取消其中file_id的概念;
删除BPPageHandle,直接使用Frame;
BPManager更名BPFrameManager;
BPFileSubHeader改为BPFileHeader并直接放在DiskBufferPool中
上级 7ad72565
...@@ -36,6 +36,8 @@ See the Mulan PSL v2 for more details. */ ...@@ -36,6 +36,8 @@ See the Mulan PSL v2 for more details. */
#include "sql/query_cache/query_cache_stage.h" #include "sql/query_cache/query_cache_stage.h"
#include "storage/default/default_storage_stage.h" #include "storage/default/default_storage_stage.h"
#include "storage/mem/mem_storage_stage.h" #include "storage/mem/mem_storage_stage.h"
#include "storage/default/disk_buffer_pool.h"
#include "storage/default/default_handler.h"
using namespace common; using namespace common;
...@@ -156,6 +158,33 @@ int prepare_init_seda() ...@@ -156,6 +158,33 @@ int prepare_init_seda()
return 0; return 0;
} }
int init_global_objects()
{
BufferPoolManager *bpm = new BufferPoolManager();
BufferPoolManager::set_instance(bpm);
DefaultHandler *handler = new DefaultHandler();
DefaultHandler::set_default(handler);
return 0;
}
int uninit_global_objects()
{
DefaultHandler *default_handler = &DefaultHandler::get_default();
if (default_handler != nullptr) {
DefaultHandler::set_default(nullptr);
delete default_handler;
}
BufferPoolManager *bpm = &BufferPoolManager::instance();
if (bpm != nullptr) {
BufferPoolManager::set_instance(nullptr);
delete bpm;
}
return 0;
}
int init(ProcessParam *process_param) int init(ProcessParam *process_param)
{ {
...@@ -200,6 +229,12 @@ int init(ProcessParam *process_param) ...@@ -200,6 +229,12 @@ int init(ProcessParam *process_param)
get_properties()->to_string(conf_data); get_properties()->to_string(conf_data);
LOG_INFO("Output configuration \n%s", conf_data.c_str()); LOG_INFO("Output configuration \n%s", conf_data.c_str());
rc = init_global_objects();
if (rc != 0) {
LOG_ERROR("failed to init global objects");
return rc;
}
// seda is used for backend async event handler // seda is used for backend async event handler
// the latency of seda is slow, it isn't used for critical latency // the latency of seda is slow, it isn't used for critical latency
// environment. // environment.
...@@ -229,7 +264,8 @@ int init(ProcessParam *process_param) ...@@ -229,7 +264,8 @@ int init(ProcessParam *process_param)
void cleanup_util() void cleanup_util()
{ {
uninit_global_objects();
if (nullptr != get_properties()) { if (nullptr != get_properties()) {
delete get_properties(); delete get_properties();
get_properties() = nullptr; get_properties() = nullptr;
...@@ -245,4 +281,6 @@ void cleanup_util() ...@@ -245,4 +281,6 @@ void cleanup_util()
} }
void cleanup() void cleanup()
{} {
cleanup_util();
}
...@@ -16,10 +16,10 @@ See the Mulan PSL v2 for more details. */ ...@@ -16,10 +16,10 @@ See the Mulan PSL v2 for more details. */
#include <string> #include <string>
static const char *TABLE_META_SUFFIX = ".table"; static constexpr const char *TABLE_META_SUFFIX = ".table";
static const char *TABLE_META_FILE_PATTERN = ".*\\.table$"; static constexpr const char *TABLE_META_FILE_PATTERN = ".*\\.table$";
static const char *TABLE_DATA_SUFFIX = ".data"; static constexpr const char *TABLE_DATA_SUFFIX = ".data";
static const char *TABLE_INDEX_SUFFIX = ".index"; static constexpr const char *TABLE_INDEX_SUFFIX = ".index";
std::string table_meta_file(const char *base_dir, const char *table_name); std::string table_meta_file(const char *base_dir, const char *table_name);
std::string table_data_file(const char *base_dir, const char *table_name); std::string table_data_file(const char *base_dir, const char *table_name);
......
...@@ -47,66 +47,54 @@ int page_header_size(int record_capacity) ...@@ -47,66 +47,54 @@ int page_header_size(int record_capacity)
return align8(page_fix_size() + bitmap_size); return align8(page_fix_size() + bitmap_size);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
RecordPageHandler::RecordPageHandler()
: disk_buffer_pool_(nullptr), file_id_(-1), page_header_(nullptr), bitmap_(nullptr)
{
page_handle_.open = false;
page_handle_.frame = nullptr;
}
RecordPageHandler::~RecordPageHandler() RecordPageHandler::~RecordPageHandler()
{ {
cleanup(); cleanup();
} }
RC RecordPageHandler::init(DiskBufferPool &buffer_pool, int file_id, PageNum page_num) RC RecordPageHandler::init(DiskBufferPool &buffer_pool, PageNum page_num)
{ {
if (disk_buffer_pool_ != nullptr) { if (disk_buffer_pool_ != nullptr) {
LOG_WARN("Disk buffer pool has been opened for file_id:page_num %d:%d.", file_id, page_num); LOG_WARN("Disk buffer pool has been opened for page_num %d.", page_num);
return RC::RECORD_OPENNED; return RC::RECORD_OPENNED;
} }
RC ret = RC::SUCCESS; RC ret = RC::SUCCESS;
if ((ret = buffer_pool.get_this_page(file_id, page_num, &page_handle_)) != RC::SUCCESS) { if ((ret = buffer_pool.get_this_page(page_num, &frame_)) != RC::SUCCESS) {
LOG_ERROR("Failed to get page handle from disk buffer pool. file_id:%d, ret=%d:%s", file_id, ret, strrc(ret)); LOG_ERROR("Failed to get page handle from disk buffer pool. ret=%d:%s", ret, strrc(ret));
return ret; return ret;
} }
char *data; char *data = frame_->data();
ret = buffer_pool.get_data(&page_handle_, &data);
if (ret != RC::SUCCESS) {
LOG_ERROR("Failed to get page data. ret=%d:%s", ret, strrc(ret));
return ret;
}
disk_buffer_pool_ = &buffer_pool; disk_buffer_pool_ = &buffer_pool;
file_id_ = file_id;
page_header_ = (PageHeader *)(data); page_header_ = (PageHeader *)(data);
bitmap_ = data + page_fix_size(); bitmap_ = data + page_fix_size();
LOG_TRACE("Successfully init file_id:page_num %d:%d.", file_id, page_num); LOG_TRACE("Successfully init page_num %d.", page_num);
return ret; return ret;
} }
RC RecordPageHandler::init_empty_page(DiskBufferPool &buffer_pool, int file_id, PageNum page_num, int record_size) RC RecordPageHandler::init_empty_page(DiskBufferPool &buffer_pool, PageNum page_num, int record_size)
{ {
RC ret = init(buffer_pool, file_id, page_num); RC ret = init(buffer_pool, page_num);
if (ret != RC::SUCCESS) { if (ret != RC::SUCCESS) {
LOG_ERROR("Failed to init empty page file_id:page_num:record_size %d:%d:%d.", file_id, page_num, record_size); LOG_ERROR("Failed to init empty page page_num:record_size %d:%d.", page_num, record_size);
return ret; return ret;
} }
int page_size = sizeof(page_handle_.frame->page.data); int page_size = BP_PAGE_DATA_SIZE;
int record_phy_size = align8(record_size); int record_phy_size = align8(record_size);
page_header_->record_num = 0; page_header_->record_num = 0;
page_header_->record_capacity = page_record_capacity(page_size, record_phy_size); page_header_->record_capacity = page_record_capacity(page_size, record_phy_size);
page_header_->record_real_size = record_size; page_header_->record_real_size = record_size;
page_header_->record_size = record_phy_size; page_header_->record_size = record_phy_size;
page_header_->first_record_offset = page_header_size(page_header_->record_capacity); page_header_->first_record_offset = page_header_size(page_header_->record_capacity);
bitmap_ = page_handle_.frame->page.data + page_fix_size(); bitmap_ = frame_->data() + page_fix_size();
memset(bitmap_, 0, page_bitmap_size(page_header_->record_capacity)); memset(bitmap_, 0, page_bitmap_size(page_header_->record_capacity));
disk_buffer_pool_->mark_dirty(&page_handle_); frame_->mark_dirty();
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -114,10 +102,8 @@ RC RecordPageHandler::init_empty_page(DiskBufferPool &buffer_pool, int file_id, ...@@ -114,10 +102,8 @@ RC RecordPageHandler::init_empty_page(DiskBufferPool &buffer_pool, int file_id,
RC RecordPageHandler::cleanup() RC RecordPageHandler::cleanup()
{ {
if (disk_buffer_pool_ != nullptr) { if (disk_buffer_pool_ != nullptr) {
disk_buffer_pool_->unpin_page(&page_handle_); disk_buffer_pool_->unpin_page(frame_);
disk_buffer_pool_ = nullptr; disk_buffer_pool_ = nullptr;
// skip purge page,
// skip reset page_header & bitmap
} }
return RC::SUCCESS; return RC::SUCCESS;
...@@ -125,9 +111,8 @@ RC RecordPageHandler::cleanup() ...@@ -125,9 +111,8 @@ RC RecordPageHandler::cleanup()
RC RecordPageHandler::insert_record(const char *data, RID *rid) RC RecordPageHandler::insert_record(const char *data, RID *rid)
{ {
if (page_header_->record_num == page_header_->record_capacity) { if (page_header_->record_num == page_header_->record_capacity) {
LOG_WARN("Page is full, file_id:page_num %d:%d.", file_id_, page_handle_.frame->page.page_num); LOG_WARN("Page is full, page_num %d:%d.", frame_->page_num());
return RC::RECORD_NOMEM; return RC::RECORD_NOMEM;
} }
...@@ -141,7 +126,7 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid) ...@@ -141,7 +126,7 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid)
char *record_data = get_record_data(index); char *record_data = get_record_data(index);
memcpy(record_data, data, page_header_->record_real_size); memcpy(record_data, data, page_header_->record_real_size);
disk_buffer_pool_->mark_dirty(&page_handle_); frame_->mark_dirty();
if (rid) { if (rid) {
rid->page_num = get_page_num(); rid->page_num = get_page_num();
...@@ -155,25 +140,21 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid) ...@@ -155,25 +140,21 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid)
RC RecordPageHandler::update_record(const Record *rec) RC RecordPageHandler::update_record(const Record *rec)
{ {
if (rec->rid.slot_num >= page_header_->record_capacity) { if (rec->rid.slot_num >= page_header_->record_capacity) {
LOG_ERROR("Invalid slot_num %d, exceed page's record capacity, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num %d, exceed page's record capacity, page_num %d.",
rec->rid.slot_num, rec->rid.slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::INVALID_ARGUMENT; return RC::INVALID_ARGUMENT;
} }
Bitmap bitmap(bitmap_, page_header_->record_capacity); Bitmap bitmap(bitmap_, page_header_->record_capacity);
if (!bitmap.get_bit(rec->rid.slot_num)) { if (!bitmap.get_bit(rec->rid.slot_num)) {
LOG_ERROR("Invalid slot_num %d, slot is empty, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num %d, slot is empty, page_num %d.",
rec->rid.slot_num, rec->rid.slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::RECORD_RECORD_NOT_EXIST; return RC::RECORD_RECORD_NOT_EXIST;
} else { } else {
char *record_data = get_record_data(rec->rid.slot_num); char *record_data = get_record_data(rec->rid.slot_num);
memcpy(record_data, rec->data, page_header_->record_real_size); memcpy(record_data, rec->data, page_header_->record_real_size);
bitmap.set_bit(rec->rid.slot_num); bitmap.set_bit(rec->rid.slot_num);
disk_buffer_pool_->mark_dirty(&page_handle_); frame_->mark_dirty();
// LOG_TRACE("Update record. file_id=%d, page num=%d,slot=%d", file_id_, rec->rid.page_num, rec->rid.slot_num); // LOG_TRACE("Update record. file_id=%d, page num=%d,slot=%d", file_id_, rec->rid.page_num, rec->rid.slot_num);
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -182,10 +163,8 @@ RC RecordPageHandler::update_record(const Record *rec) ...@@ -182,10 +163,8 @@ RC RecordPageHandler::update_record(const Record *rec)
RC RecordPageHandler::delete_record(const RID *rid) RC RecordPageHandler::delete_record(const RID *rid)
{ {
if (rid->slot_num >= page_header_->record_capacity) { if (rid->slot_num >= page_header_->record_capacity) {
LOG_ERROR("Invalid slot_num %d, exceed page's record capacity, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num %d, exceed page's record capacity, page_num %d.",
rid->slot_num, rid->slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::INVALID_ARGUMENT; return RC::INVALID_ARGUMENT;
} }
...@@ -193,21 +172,18 @@ RC RecordPageHandler::delete_record(const RID *rid) ...@@ -193,21 +172,18 @@ RC RecordPageHandler::delete_record(const RID *rid)
if (bitmap.get_bit(rid->slot_num)) { if (bitmap.get_bit(rid->slot_num)) {
bitmap.clear_bit(rid->slot_num); bitmap.clear_bit(rid->slot_num);
page_header_->record_num--; page_header_->record_num--;
disk_buffer_pool_->mark_dirty(&page_handle_); frame_->mark_dirty();
if (page_header_->record_num == 0) { if (page_header_->record_num == 0) {
DiskBufferPool *disk_buffer_pool = disk_buffer_pool_; DiskBufferPool *disk_buffer_pool = disk_buffer_pool_;
int file_id = file_id_;
PageNum page_num = get_page_num(); PageNum page_num = get_page_num();
cleanup(); cleanup();
disk_buffer_pool->dispose_page(file_id, page_num); disk_buffer_pool->dispose_page(page_num);
} }
return RC::SUCCESS; return RC::SUCCESS;
} else { } else {
LOG_ERROR("Invalid slot_num %d, slot is empty, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num %d, slot is empty, page_num %d.",
rid->slot_num, rid->slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::RECORD_RECORD_NOT_EXIST; return RC::RECORD_RECORD_NOT_EXIST;
} }
} }
...@@ -215,19 +191,15 @@ RC RecordPageHandler::delete_record(const RID *rid) ...@@ -215,19 +191,15 @@ RC RecordPageHandler::delete_record(const RID *rid)
RC RecordPageHandler::get_record(const RID *rid, Record *rec) RC RecordPageHandler::get_record(const RID *rid, Record *rec)
{ {
if (rid->slot_num >= page_header_->record_capacity) { if (rid->slot_num >= page_header_->record_capacity) {
LOG_ERROR("Invalid slot_num:%d, exceed page's record capacity, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num:%d, exceed page's record capacity, page_num %d.",
rid->slot_num, rid->slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::RECORD_INVALIDRID; return RC::RECORD_INVALIDRID;
} }
Bitmap bitmap(bitmap_, page_header_->record_capacity); Bitmap bitmap(bitmap_, page_header_->record_capacity);
if (!bitmap.get_bit(rid->slot_num)) { if (!bitmap.get_bit(rid->slot_num)) {
LOG_ERROR("Invalid slot_num:%d, slot is empty, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num:%d, slot is empty, page_num %d.",
rid->slot_num, rid->slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::RECORD_RECORD_NOT_EXIST; return RC::RECORD_RECORD_NOT_EXIST;
} }
...@@ -245,10 +217,8 @@ RC RecordPageHandler::get_first_record(Record *rec) ...@@ -245,10 +217,8 @@ RC RecordPageHandler::get_first_record(Record *rec)
RC RecordPageHandler::get_next_record(Record *rec) RC RecordPageHandler::get_next_record(Record *rec)
{ {
if (rec->rid.slot_num >= page_header_->record_capacity - 1) { if (rec->rid.slot_num >= page_header_->record_capacity - 1) {
LOG_ERROR("Invalid slot_num:%d, exceed page's record capacity, file_id:page_num %d:%d.", LOG_ERROR("Invalid slot_num:%d, exceed page's record capacity, page_num %d.",
rec->rid.slot_num, rec->rid.slot_num, frame_->page_num());
file_id_,
page_handle_.frame->page.page_num);
return RC::RECORD_EOF; return RC::RECORD_EOF;
} }
...@@ -256,7 +226,7 @@ RC RecordPageHandler::get_next_record(Record *rec) ...@@ -256,7 +226,7 @@ RC RecordPageHandler::get_next_record(Record *rec)
int index = bitmap.next_setted_bit(rec->rid.slot_num + 1); int index = bitmap.next_setted_bit(rec->rid.slot_num + 1);
if (index < 0) { if (index < 0) {
LOG_WARN("There is no empty slot on page -- file_id:%d, page_num:%d.", file_id_, page_handle_.frame->page.page_num); LOG_WARN("There is no empty slot on page -- page_num:%d.", frame_->page_num());
return RC::RECORD_EOF; return RC::RECORD_EOF;
} }
...@@ -271,7 +241,7 @@ PageNum RecordPageHandler::get_page_num() const ...@@ -271,7 +241,7 @@ PageNum RecordPageHandler::get_page_num() const
if (nullptr == page_header_) { if (nullptr == page_header_) {
return (PageNum)(-1); return (PageNum)(-1);
} }
return page_handle_.frame->page.page_num; return frame_->page_num();
} }
bool RecordPageHandler::is_full() const bool RecordPageHandler::is_full() const
...@@ -281,21 +251,16 @@ bool RecordPageHandler::is_full() const ...@@ -281,21 +251,16 @@ bool RecordPageHandler::is_full() const
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
RecordFileHandler::RecordFileHandler() : disk_buffer_pool_(nullptr), file_id_(-1) RC RecordFileHandler::init(DiskBufferPool *buffer_pool)
{}
RC RecordFileHandler::init(DiskBufferPool *buffer_pool, int file_id)
{ {
if (disk_buffer_pool_ != nullptr) { if (disk_buffer_pool_ != nullptr) {
LOG_ERROR("%d has been openned.", file_id); LOG_ERROR("record file handler has been openned.");
return RC::RECORD_OPENNED; return RC::RECORD_OPENNED;
} }
disk_buffer_pool_ = buffer_pool; disk_buffer_pool_ = buffer_pool;
file_id_ = file_id;
LOG_INFO("Successfully open %d.", file_id); LOG_INFO("Successfully open record file handle");
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -311,8 +276,8 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid) ...@@ -311,8 +276,8 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid)
RC ret = RC::SUCCESS; RC ret = RC::SUCCESS;
// 找到没有填满的页面 // 找到没有填满的页面
int page_count = 0; int page_count = 0;
if ((ret = disk_buffer_pool_->get_page_count(file_id_, &page_count)) != RC::SUCCESS) { if ((ret = disk_buffer_pool_->get_page_count(&page_count)) != RC::SUCCESS) {
LOG_ERROR("Failed to get page count while inserting record, file_id:%d", this->file_id_); LOG_ERROR("Failed to get page count while inserting record");
return ret; return ret;
} }
...@@ -321,8 +286,8 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid) ...@@ -321,8 +286,8 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid)
if (page_count >= 2) { if (page_count >= 2) {
// 当前buffer pool 有页面时才尝试加载第一页 // 当前buffer pool 有页面时才尝试加载第一页
// 参考diskBufferPool,有效page的pageNum从1开始 // 参考diskBufferPool,有效page的pageNum从1开始
if ((ret = record_page_handler_.init(*disk_buffer_pool_, file_id_, 1)) != RC::SUCCESS) { if ((ret = record_page_handler_.init(*disk_buffer_pool_, 1)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler, file_id:%d, ret=%d", file_id_, ret); LOG_ERROR("Failed to init record page handler, ret=%d", ret);
return ret; return ret;
} }
current_page_num = record_page_handler_.get_page_num(); current_page_num = record_page_handler_.get_page_num();
...@@ -339,10 +304,10 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid) ...@@ -339,10 +304,10 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid)
} }
if (current_page_num != record_page_handler_.get_page_num()) { if (current_page_num != record_page_handler_.get_page_num()) {
record_page_handler_.cleanup(); record_page_handler_.cleanup();
ret = record_page_handler_.init(*disk_buffer_pool_, file_id_, current_page_num); ret = record_page_handler_.init(*disk_buffer_pool_, current_page_num);
if (ret != RC::SUCCESS && ret != RC::BUFFERPOOL_INVALID_PAGE_NUM) { if (ret != RC::SUCCESS && ret != RC::BUFFERPOOL_INVALID_PAGE_NUM) {
LOG_ERROR( LOG_ERROR("Failed to init record page handler. page number is %d. ret=%d:%s",
"Failed to init record page handler. page number is %d. ret=%d:%s", current_page_num, ret, strrc(ret)); current_page_num, ret, strrc(ret));
return ret; return ret;
} }
} }
...@@ -355,27 +320,24 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid) ...@@ -355,27 +320,24 @@ RC RecordFileHandler::insert_record(const char *data, int record_size, RID *rid)
// 找不到就分配一个新的页面 // 找不到就分配一个新的页面
if (!page_found) { if (!page_found) {
BPPageHandle page_handle; Frame *frame = nullptr;
if ((ret = disk_buffer_pool_->allocate_page(file_id_, &page_handle)) != RC::SUCCESS) { if ((ret = disk_buffer_pool_->allocate_page(&frame)) != RC::SUCCESS) {
LOG_ERROR("Failed to allocate page while inserting record. file_it:%d, ret:%d", file_id_, ret); LOG_ERROR("Failed to allocate page while inserting record. ret:%d", ret);
return ret; return ret;
} }
current_page_num = page_handle.frame->page.page_num; current_page_num = frame->page_num();
record_page_handler_.cleanup(); record_page_handler_.cleanup();
ret = record_page_handler_.init_empty_page(*disk_buffer_pool_, file_id_, current_page_num, record_size); ret = record_page_handler_.init_empty_page(*disk_buffer_pool_, current_page_num, record_size);
if (ret != RC::SUCCESS) { if (ret != RC::SUCCESS) {
LOG_ERROR("Failed to init empty page. file_id:%d, ret:%d", file_id_, ret); LOG_ERROR("Failed to init empty page. ret:%d", ret);
if (RC::SUCCESS != disk_buffer_pool_->unpin_page(&page_handle)) { if (RC::SUCCESS != disk_buffer_pool_->unpin_page(frame)) {
LOG_ERROR("Failed to unpin page. file_id:%d", file_id_); LOG_ERROR("Failed to unpin page. ");
} }
return ret; return ret;
} }
//@@@ TODO, remove unpin page here disk_buffer_pool_->unpin_page(frame);
// if (RC::SUCCESS != disk_buffer_pool_->unpin_page(&page_handle)) {
// LOG_ERROR("Failed to unpin page. file_id:%d", file_id_);
// }
} }
// 找到空闲位置 // 找到空闲位置
...@@ -390,8 +352,8 @@ RC RecordFileHandler::update_record(const Record *rec) ...@@ -390,8 +352,8 @@ RC RecordFileHandler::update_record(const Record *rec)
} }
RC ret; RC ret;
RecordPageHandler page_handler; RecordPageHandler page_handler;
if ((ret = page_handler.init(*disk_buffer_pool_, file_id_, rec->rid.page_num)) != RC::SUCCESS) { if ((ret = page_handler.init(*disk_buffer_pool_, rec->rid.page_num)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler.page number=%d, file_id=%d", rec->rid.page_num, file_id_); LOG_ERROR("Failed to init record page handler.page number=%d", rec->rid.page_num);
return ret; return ret;
} }
...@@ -406,8 +368,8 @@ RC RecordFileHandler::delete_record(const RID *rid) ...@@ -406,8 +368,8 @@ RC RecordFileHandler::delete_record(const RID *rid)
RC ret = RC::SUCCESS; RC ret = RC::SUCCESS;
RecordPageHandler page_handler; RecordPageHandler page_handler;
if ((ret != page_handler.init(*disk_buffer_pool_, file_id_, rid->page_num)) != RC::SUCCESS) { if ((ret != page_handler.init(*disk_buffer_pool_, rid->page_num)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler.page number=%d, file_id:%d", rid->page_num, file_id_); LOG_ERROR("Failed to init record page handler.page number=%d", rid->page_num);
return ret; return ret;
} }
return page_handler.delete_record(rid); return page_handler.delete_record(rid);
...@@ -427,8 +389,8 @@ RC RecordFileHandler::get_record(const RID *rid, Record *rec) ...@@ -427,8 +389,8 @@ RC RecordFileHandler::get_record(const RID *rid, Record *rec)
} }
RecordPageHandler page_handler; RecordPageHandler page_handler;
if ((ret != page_handler.init(*disk_buffer_pool_, file_id_, rid->page_num)) != RC::SUCCESS) { if ((ret != page_handler.init(*disk_buffer_pool_, rid->page_num)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler.page number=%d, file_id:%d", rid->page_num, file_id_); LOG_ERROR("Failed to init record page handler.page number=%d", rid->page_num);
return ret; return ret;
} }
...@@ -437,15 +399,11 @@ RC RecordFileHandler::get_record(const RID *rid, Record *rec) ...@@ -437,15 +399,11 @@ RC RecordFileHandler::get_record(const RID *rid, Record *rec)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
RecordFileScanner::RecordFileScanner() : disk_buffer_pool_(nullptr), file_id_(-1), condition_filter_(nullptr) RC RecordFileScanner::open_scan(DiskBufferPool &buffer_pool, ConditionFilter *condition_filter)
{}
RC RecordFileScanner::open_scan(DiskBufferPool &buffer_pool, int file_id, ConditionFilter *condition_filter)
{ {
close_scan(); close_scan();
disk_buffer_pool_ = &buffer_pool; disk_buffer_pool_ = &buffer_pool;
file_id_ = file_id;
condition_filter_ = condition_filter; condition_filter_ = condition_filter;
return RC::SUCCESS; return RC::SUCCESS;
...@@ -483,8 +441,8 @@ RC RecordFileScanner::get_next_record(Record *rec) ...@@ -483,8 +441,8 @@ RC RecordFileScanner::get_next_record(Record *rec)
Record current_record = *rec; Record current_record = *rec;
int page_count = 0; int page_count = 0;
if ((ret = disk_buffer_pool_->get_page_count(file_id_, &page_count)) != RC::SUCCESS) { if ((ret = disk_buffer_pool_->get_page_count(&page_count)) != RC::SUCCESS) {
LOG_ERROR("Failed to get page count while getting next record. file id=%d", file_id_); LOG_ERROR("Failed to get page count while getting next record.");
return RC::RECORD_EOF; return RC::RECORD_EOF;
} }
...@@ -496,7 +454,7 @@ RC RecordFileScanner::get_next_record(Record *rec) ...@@ -496,7 +454,7 @@ RC RecordFileScanner::get_next_record(Record *rec)
if (current_record.rid.page_num != record_page_handler_.get_page_num()) { if (current_record.rid.page_num != record_page_handler_.get_page_num()) {
record_page_handler_.cleanup(); record_page_handler_.cleanup();
ret = record_page_handler_.init(*disk_buffer_pool_, file_id_, current_record.rid.page_num); ret = record_page_handler_.init(*disk_buffer_pool_, current_record.rid.page_num);
if (ret != RC::SUCCESS && ret != RC::BUFFERPOOL_INVALID_PAGE_NUM) { if (ret != RC::SUCCESS && ret != RC::BUFFERPOOL_INVALID_PAGE_NUM) {
LOG_ERROR("Failed to init record page handler. page num=%d", current_record.rid.page_num); LOG_ERROR("Failed to init record page handler. page num=%d", current_record.rid.page_num);
return ret; return ret;
......
...@@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */
#define __OBSERVER_STORAGE_COMMON_RECORD_MANAGER_H_ #define __OBSERVER_STORAGE_COMMON_RECORD_MANAGER_H_
#include <sstream> #include <sstream>
#include <limits>
#include "storage/default/disk_buffer_pool.h" #include "storage/default/disk_buffer_pool.h"
typedef int32_t SlotNum; typedef int32_t SlotNum;
...@@ -96,10 +97,10 @@ struct Record { ...@@ -96,10 +97,10 @@ struct Record {
class RecordPageHandler { class RecordPageHandler {
public: public:
RecordPageHandler(); RecordPageHandler() = default;
~RecordPageHandler(); ~RecordPageHandler();
RC init(DiskBufferPool &buffer_pool, int file_id, PageNum page_num); RC init(DiskBufferPool &buffer_pool, PageNum page_num);
RC init_empty_page(DiskBufferPool &buffer_pool, int file_id, PageNum page_num, int record_size); RC init_empty_page(DiskBufferPool &buffer_pool, PageNum page_num, int record_size);
RC cleanup(); RC cleanup();
RC insert_record(const char *data, RID *rid); RC insert_record(const char *data, RID *rid);
...@@ -114,7 +115,7 @@ public: ...@@ -114,7 +115,7 @@ public:
return rc; return rc;
} }
rc = updater(record); rc = updater(record);
disk_buffer_pool_->mark_dirty(&page_handle_); frame_->mark_dirty();
return rc; return rc;
} }
...@@ -131,51 +132,40 @@ public: ...@@ -131,51 +132,40 @@ public:
protected: protected:
char *get_record_data(SlotNum slot_num) char *get_record_data(SlotNum slot_num)
{ {
return page_handle_.frame->page.data + page_header_->first_record_offset + (page_header_->record_size * slot_num); return frame_->data() + page_header_->first_record_offset + (page_header_->record_size * slot_num);
} }
protected: protected:
DiskBufferPool *disk_buffer_pool_; DiskBufferPool *disk_buffer_pool_ = nullptr;
int file_id_; Frame *frame_ = nullptr;
BPPageHandle page_handle_; PageHeader *page_header_ = nullptr;
PageHeader *page_header_; char *bitmap_ = nullptr;
char *bitmap_;
}; };
class RecordFileHandler { class RecordFileHandler {
public: public:
RecordFileHandler(); RecordFileHandler() = default;
RC init(DiskBufferPool *buffer_pool, int file_id); RC init(DiskBufferPool *buffer_pool);
void close(); void close();
/** /**
* 更新指定文件中的记录,rec指向的记录结构中的rid字段为要更新的记录的标识符, * 更新指定文件中的记录,rec指向的记录结构中的rid字段为要更新的记录的标识符,
* pData字段指向新的记录内容 * pData字段指向新的记录内容
* @param rec
* @return
*/ */
RC update_record(const Record *rec); RC update_record(const Record *rec);
/** /**
* 从指定文件中删除标识符为rid的记录 * 从指定文件中删除标识符为rid的记录
* @param rid
* @return
*/ */
RC delete_record(const RID *rid); RC delete_record(const RID *rid);
/** /**
* 插入一个新的记录到指定文件中,pData为指向新纪录内容的指针,返回该记录的标识符rid * 插入一个新的记录到指定文件中,pData为指向新纪录内容的指针,返回该记录的标识符rid
* @param data
* @param rid
* @return
*/ */
RC insert_record(const char *data, int record_size, RID *rid); RC insert_record(const char *data, int record_size, RID *rid);
/** /**
* 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中 * 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中
* @param rid
* @param rec
* @return
*/ */
RC get_record(const RID *rid, Record *rec); RC get_record(const RID *rid, Record *rec);
...@@ -185,7 +175,7 @@ public: ...@@ -185,7 +175,7 @@ public:
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
RecordPageHandler page_handler; RecordPageHandler page_handler;
if ((rc != page_handler.init(*disk_buffer_pool_, file_id_, rid->page_num)) != RC::SUCCESS) { if ((rc != page_handler.init(*disk_buffer_pool_, rid->page_num)) != RC::SUCCESS) {
return rc; return rc;
} }
...@@ -193,15 +183,13 @@ public: ...@@ -193,15 +183,13 @@ public:
} }
private: private:
DiskBufferPool *disk_buffer_pool_; DiskBufferPool *disk_buffer_pool_ = nullptr;
int file_id_; // 参考DiskBufferPool中的fileId
RecordPageHandler record_page_handler_; // 目前只有insert record使用 RecordPageHandler record_page_handler_; // 目前只有insert record使用
}; };
class RecordFileScanner { class RecordFileScanner {
public: public:
RecordFileScanner(); RecordFileScanner() = default;
/** /**
* 打开一个文件扫描。 * 打开一个文件扫描。
...@@ -210,13 +198,8 @@ public: ...@@ -210,13 +198,8 @@ public:
* 然后再调用GetNextRec函数来逐个返回文件中满足条件的记录。 * 然后再调用GetNextRec函数来逐个返回文件中满足条件的记录。
* 如果条件数量conNum为0,则意味着检索文件中的所有记录。 * 如果条件数量conNum为0,则意味着检索文件中的所有记录。
* 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回 * 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回
* @param buffer_pool
* @param file_id
* @param condition_num
* @param conditions
* @return
*/ */
RC open_scan(DiskBufferPool &buffer_pool, int file_id, ConditionFilter *condition_filter); RC open_scan(DiskBufferPool &buffer_pool, ConditionFilter *condition_filter);
/** /**
* 关闭一个文件扫描,释放相应的资源 * 关闭一个文件扫描,释放相应的资源
...@@ -236,10 +219,9 @@ public: ...@@ -236,10 +219,9 @@ public:
RC get_next_record(Record *rec); RC get_next_record(Record *rec);
private: private:
DiskBufferPool *disk_buffer_pool_; DiskBufferPool *disk_buffer_pool_ = nullptr;
int file_id_; // 参考DiskBufferPool中的fileId
ConditionFilter *condition_filter_; ConditionFilter *condition_filter_ = nullptr;
RecordPageHandler record_page_handler_; RecordPageHandler record_page_handler_;
}; };
......
...@@ -29,9 +29,6 @@ See the Mulan PSL v2 for more details. */ ...@@ -29,9 +29,6 @@ See the Mulan PSL v2 for more details. */
#include "storage/index/bplus_tree_index.h" #include "storage/index/bplus_tree_index.h"
#include "storage/trx/trx.h" #include "storage/trx/trx.h"
Table::Table() : data_buffer_pool_(nullptr), file_id_(-1), record_handler_(nullptr)
{}
Table::~Table() Table::~Table()
{ {
if (record_handler_ != nullptr) { if (record_handler_ != nullptr) {
...@@ -39,8 +36,8 @@ Table::~Table() ...@@ -39,8 +36,8 @@ Table::~Table()
record_handler_ = nullptr; record_handler_ = nullptr;
} }
if (data_buffer_pool_ != nullptr && file_id_ >= 0) { if (data_buffer_pool_ != nullptr) {
data_buffer_pool_->close_file(file_id_); data_buffer_pool_->close_file();
data_buffer_pool_ = nullptr; data_buffer_pool_ = nullptr;
} }
...@@ -102,8 +99,8 @@ RC Table::create( ...@@ -102,8 +99,8 @@ RC Table::create(
fs.close(); fs.close();
std::string data_file = table_data_file(base_dir, name); std::string data_file = table_data_file(base_dir, name);
data_buffer_pool_ = theGlobalDiskBufferPool(); BufferPoolManager &bpm = BufferPoolManager::instance();
rc = data_buffer_pool_->create_file(data_file.c_str()); rc = bpm.create_file(data_file.c_str());
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to create disk buffer pool of data file. file name=%s", data_file.c_str()); LOG_ERROR("Failed to create disk buffer pool of data file. file name=%s", data_file.c_str());
return rc; return rc;
...@@ -339,28 +336,24 @@ RC Table::make_record(int value_num, const Value *values, char *&record_out) ...@@ -339,28 +336,24 @@ RC Table::make_record(int value_num, const Value *values, char *&record_out)
RC Table::init_record_handler(const char *base_dir) RC Table::init_record_handler(const char *base_dir)
{ {
std::string data_file = table_data_file(base_dir, table_meta_.name()); std::string data_file = table_data_file(base_dir, table_meta_.name());
if (nullptr == data_buffer_pool_) {
data_buffer_pool_ = theGlobalDiskBufferPool();
}
int data_buffer_pool_file_id; RC rc = BufferPoolManager::instance().open_file(data_file.c_str(), data_buffer_pool_);
RC rc = data_buffer_pool_->open_file(data_file.c_str(), &data_buffer_pool_file_id);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to open disk buffer pool for file:%s. rc=%d:%s", data_file.c_str(), rc, strrc(rc)); LOG_ERROR("Failed to open disk buffer pool for file:%s. rc=%d:%s", data_file.c_str(), rc, strrc(rc));
return rc; return rc;
} }
record_handler_ = new RecordFileHandler(); record_handler_ = new RecordFileHandler();
rc = record_handler_->init(data_buffer_pool_, data_buffer_pool_file_id); rc = record_handler_->init(data_buffer_pool_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to init record handler. rc=%d:%s", rc, strrc(rc)); LOG_ERROR("Failed to init record handler. rc=%d:%s", rc, strrc(rc));
data_buffer_pool_->close_file(data_buffer_pool_file_id); data_buffer_pool_->close_file();
data_buffer_pool_ = nullptr;
delete record_handler_; delete record_handler_;
record_handler_ = nullptr; record_handler_ = nullptr;
return rc; return rc;
} }
file_id_ = data_buffer_pool_file_id;
return rc; return rc;
} }
...@@ -419,9 +412,9 @@ RC Table::scan_record( ...@@ -419,9 +412,9 @@ RC Table::scan_record(
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
RecordFileScanner scanner; RecordFileScanner scanner;
rc = scanner.open_scan(*data_buffer_pool_, file_id_, filter); rc = scanner.open_scan(*data_buffer_pool_, filter);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("failed to open scanner. file id=%d. rc=%d:%s", file_id_, rc, strrc(rc)); LOG_ERROR("failed to open scanner. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
...@@ -441,7 +434,7 @@ RC Table::scan_record( ...@@ -441,7 +434,7 @@ RC Table::scan_record(
if (RC::RECORD_EOF == rc) { if (RC::RECORD_EOF == rc) {
rc = RC::SUCCESS; rc = RC::SUCCESS;
} else { } else {
LOG_ERROR("failed to scan record. file id=%d, rc=%d:%s", file_id_, rc, strrc(rc)); LOG_ERROR("failed to scan record. rc=%d:%s", rc, strrc(rc));
} }
scanner.close_scan(); scanner.close_scan();
return rc; return rc;
...@@ -834,7 +827,7 @@ IndexScanner *Table::find_index_for_scan(const ConditionFilter *filter) ...@@ -834,7 +827,7 @@ IndexScanner *Table::find_index_for_scan(const ConditionFilter *filter)
RC Table::sync() RC Table::sync()
{ {
RC rc = data_buffer_pool_->purge_all_pages(file_id_); RC rc = data_buffer_pool_->purge_all_pages();
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush table's data pages. table=%s, rc=%d:%s", name(), rc, strrc(rc)); LOG_ERROR("Failed to flush table's data pages. table=%s, rc=%d:%s", name(), rc, strrc(rc));
return rc; return rc;
......
...@@ -30,7 +30,7 @@ class Trx; ...@@ -30,7 +30,7 @@ class Trx;
class Table { class Table {
public: public:
Table(); Table() = default;
~Table(); ~Table();
/** /**
...@@ -101,10 +101,9 @@ private: ...@@ -101,10 +101,9 @@ private:
private: private:
std::string base_dir_; std::string base_dir_;
TableMeta table_meta_; TableMeta table_meta_;
DiskBufferPool *data_buffer_pool_; /// 数据文件关联的buffer pool DiskBufferPool *data_buffer_pool_ = nullptr; /// 数据文件关联的buffer pool
int file_id_; RecordFileHandler *record_handler_ = nullptr; /// 记录操作
RecordFileHandler *record_handler_; /// 记录操作
std::vector<Index *> indexes_; std::vector<Index *> indexes_;
}; };
#endif // __OBSERVER_STORAGE_COMMON_TABLE_H__ #endif // __OBSERVER_STORAGE_COMMON_TABLE_H__
\ No newline at end of file
...@@ -24,10 +24,20 @@ See the Mulan PSL v2 for more details. */ ...@@ -24,10 +24,20 @@ See the Mulan PSL v2 for more details. */
#include "storage/common/table.h" #include "storage/common/table.h"
#include "storage/common/condition_filter.h" #include "storage/common/condition_filter.h"
static DefaultHandler *default_handler = nullptr;
void DefaultHandler::set_default(DefaultHandler *handler)
{
if (default_handler != nullptr && handler != nullptr) {
LOG_ERROR("default handler is setted");
abort();
}
default_handler = handler;
}
DefaultHandler &DefaultHandler::get_default() DefaultHandler &DefaultHandler::get_default()
{ {
static DefaultHandler handler; return *default_handler;
return handler;
} }
DefaultHandler::DefaultHandler() DefaultHandler::DefaultHandler()
......
...@@ -159,6 +159,7 @@ public: ...@@ -159,6 +159,7 @@ public:
RC sync(); RC sync();
public: public:
static void set_default(DefaultHandler *handler);
static DefaultHandler &get_default(); static DefaultHandler &get_default();
private: private:
...@@ -167,4 +168,4 @@ private: ...@@ -167,4 +168,4 @@ private:
std::map<std::string, Db *> opened_dbs_; std::map<std::string, Db *> opened_dbs_;
}; // class Handler }; // class Handler
#endif // __OBSERVER_STORAGE_DEFAULT_ENGINE_H__ #endif // __OBSERVER_STORAGE_DEFAULT_ENGINE_H__
\ No newline at end of file
...@@ -21,7 +21,8 @@ See the Mulan PSL v2 for more details. */ ...@@ -21,7 +21,8 @@ See the Mulan PSL v2 for more details. */
using namespace common; using namespace common;
int DiskBufferPool::POOL_NUM = MAX_OPEN_FILE / 4; static const PageNum BP_HEADER_PAGE = 0;
static const int MEM_POOL_ITEM_NUM = 50;
unsigned long current_time() unsigned long current_time()
{ {
...@@ -30,20 +31,7 @@ unsigned long current_time() ...@@ -30,20 +31,7 @@ unsigned long current_time()
return tp.tv_sec * 1000 * 1000 * 1000UL + tp.tv_nsec; return tp.tv_sec * 1000 * 1000 * 1000UL + tp.tv_nsec;
} }
BPFileHandle::BPFileHandle() BPFrameManager::BPFrameManager(const char *name) : MemPoolSimple<Frame>(name)
{
memset((void *)this, 0, sizeof(*this));
}
BPFileHandle::~BPFileHandle()
{
if (file_name != nullptr) {
::free((void *)file_name);
file_name = nullptr;
}
}
BPManager::BPManager(const char *name) : MemPoolSimple<Frame>(name)
{} {}
static bool match_purge(void *item, void *arg) static bool match_purge(void *item, void *arg)
...@@ -52,7 +40,7 @@ static bool match_purge(void *item, void *arg) ...@@ -52,7 +40,7 @@ static bool match_purge(void *item, void *arg)
return frame->can_purge(); return frame->can_purge();
} }
Frame *BPManager::begin_purge() Frame *BPFrameManager::begin_purge()
{ {
return MemPoolSimple<Frame>::find(match_purge, nullptr); return MemPoolSimple<Frame>::find(match_purge, nullptr);
} }
...@@ -72,13 +60,13 @@ static bool match_file_page(void *item, void *arg) ...@@ -72,13 +60,13 @@ static bool match_file_page(void *item, void *arg)
Frame *frame = (Frame *)item; Frame *frame = (Frame *)item;
MatchFilePage *file_page = (MatchFilePage *)arg; MatchFilePage *file_page = (MatchFilePage *)arg;
if (frame->file_desc == file_page->file_desc && frame->page.page_num == file_page->page_num) if (frame->file_desc() == file_page->file_desc && frame->page_num() == file_page->page_num)
return true; return true;
return false; return false;
} }
Frame *BPManager::get(int file_desc, PageNum page_num) Frame *BPFrameManager::get(int file_desc, PageNum page_num)
{ {
MatchFilePage file_page(file_desc, page_num); MatchFilePage file_page(file_desc, page_num);
return MemPoolSimple<Frame>::find(match_file_page, &file_page); return MemPoolSimple<Frame>::find(match_file_page, &file_page);
...@@ -89,328 +77,194 @@ static bool match_file(void *item, void *arg) ...@@ -89,328 +77,194 @@ static bool match_file(void *item, void *arg)
Frame *frame = (Frame *)item; Frame *frame = (Frame *)item;
int *file_desc = (int *)arg; int *file_desc = (int *)arg;
if (frame->file_desc == *file_desc) if (frame->file_desc() == *file_desc)
return true; return true;
return false; return false;
} }
std::list<Frame *> BPManager::find_list(int file_desc) std::list<Frame *> BPFrameManager::find_list(int file_desc)
{ {
return find_all(match_file, &file_desc); return find_all(match_file, &file_desc);
} }
DiskBufferPool *theGlobalDiskBufferPool() DiskBufferPool::DiskBufferPool(BufferPoolManager &bp_manager, BPFrameManager &frame_manager)
: bp_manager_(bp_manager), frame_manager_(frame_manager)
{ {
static DiskBufferPool *instance = DiskBufferPool::mk_instance();
return instance;
} }
DiskBufferPool::DiskBufferPool() : bp_manager_("BPManager")
{
bp_manager_.init(false, DiskBufferPool::POOL_NUM, BP_BUFFER_SIZE);
};
DiskBufferPool::~DiskBufferPool() DiskBufferPool::~DiskBufferPool()
{ {
for (int i = 0; i < MAX_OPEN_FILE; i++) { close_file();
BPFileHandle *file_handle = open_list_[i];
if (file_handle == nullptr) {
continue;
}
close_file(i);
open_list_[i] = nullptr;
}
bp_manager_.cleanup();
LOG_INFO("Exit"); LOG_INFO("Exit");
} }
RC DiskBufferPool::create_file(const char *file_name) RC DiskBufferPool::open_file(const char *file_name)
{ {
int fd = open(file_name, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE); int fd;
if (fd < 0) {
LOG_ERROR("Failed to create %s, due to %s.", file_name, strerror(errno));
return RC::SCHEMA_DB_EXIST;
}
close(fd);
/**
* Here don't care about the failure
*/
fd = open(file_name, O_RDWR);
if (fd < 0) {
LOG_ERROR("Failed to open for readwrite %s, due to %s.", file_name, strerror(errno));
return RC::IOERR_ACCESS;
}
Page page;
memset(&page, 0, sizeof(Page));
BPFileSubHeader *fileSubHeader;
fileSubHeader = (BPFileSubHeader *)page.data;
fileSubHeader->allocated_pages = 1;
fileSubHeader->page_count = 1;
char *bitmap = page.data + (int)BP_FILE_SUB_HDR_SIZE;
bitmap[0] |= 0x01;
if (lseek(fd, 0, SEEK_SET) == -1) {
LOG_ERROR("Failed to seek file %s to position 0, due to %s .", file_name, strerror(errno));
close(fd);
return RC::IOERR_SEEK;
}
if (write(fd, (char *)&page, sizeof(Page)) != sizeof(Page)) {
LOG_ERROR("Failed to write header to file %s, due to %s.", file_name, strerror(errno));
close(fd);
return RC::IOERR_WRITE;
}
close(fd);
LOG_INFO("Successfully create %s.", file_name);
return RC::SUCCESS;
}
RC DiskBufferPool::open_file(const char *file_name, int *file_id)
{
int fd, i, size = 0, empty_id = -1;
// This part isn't gentle, the better method is using LRU queue.
for (i = 0; i < MAX_OPEN_FILE; i++) {
if (open_list_[i]) {
size++;
if (!strcmp(open_list_[i]->file_name, file_name)) {
*file_id = i;
LOG_INFO("%s has already been opened.", file_name);
return RC::SUCCESS;
}
} else if (empty_id == -1) {
empty_id = i;
}
}
i = size;
if (i >= MAX_OPEN_FILE && open_list_[i - 1]) {
LOG_ERROR("Failed to open file %s, because too much files have been opened.", file_name);
return RC::BUFFERPOOL_OPEN_TOO_MANY_FILES;
}
if ((fd = open(file_name, O_RDWR)) < 0) { if ((fd = open(file_name, O_RDWR)) < 0) {
LOG_ERROR("Failed to open file %s, because %s.", file_name, strerror(errno)); LOG_ERROR("Failed to open file %s, because %s.", file_name, strerror(errno));
return RC::IOERR_ACCESS; return RC::IOERR_ACCESS;
} }
LOG_INFO("Successfully open file %s.", file_name); LOG_INFO("Successfully open file %s.", file_name);
BPFileHandle *file_handle = new (std::nothrow) BPFileHandle(); file_name_ = file_name;
if (file_handle == nullptr) { file_desc_ = fd;
LOG_ERROR("Failed to alloc memory of BPFileHandle for %s.", file_name);
close(fd);
return RC::NOMEM;
}
RC tmp = RC::SUCCESS; RC rc = RC::SUCCESS;
file_handle->bopen = true; rc = allocate_frame(&hdr_frame_);
file_handle->file_name = strdup(file_name); if (rc != RC::SUCCESS) {
file_handle->file_desc = fd; LOG_ERROR("failed to allocate frame for header. file name %s", file_name_.c_str());
if ((tmp = allocate_page(&file_handle->hdr_frame)) != RC::SUCCESS) {
LOG_ERROR("Failed to allocate block for %s's BPFileHandle.", file_name);
delete file_handle;
close(fd); close(fd);
return tmp; file_desc_ = -1;
return rc;
} }
file_handle->hdr_frame->dirty = false;
file_handle->hdr_frame->file_desc = fd; hdr_frame_->dirty_ = false;
file_handle->hdr_frame->pin_count = 1; hdr_frame_->file_desc_ = fd;
file_handle->hdr_frame->acc_time = current_time(); hdr_frame_->pin_count_ = 1;
if ((tmp = load_page(0, file_handle, file_handle->hdr_frame)) != RC::SUCCESS) { hdr_frame_->acc_time_ = current_time();
if ((rc = load_page(BP_HEADER_PAGE, hdr_frame_)) != RC::SUCCESS) {
LOG_ERROR("Failed to load first page of %s, due to %s.", file_name, strerror(errno)); LOG_ERROR("Failed to load first page of %s, due to %s.", file_name, strerror(errno));
file_handle->hdr_frame->pin_count = 0; hdr_frame_->pin_count_ = 0;
purge_page(file_handle->hdr_frame); purge_frame(hdr_frame_);
close(fd); close(fd);
delete file_handle; file_desc_ = -1;
return tmp; return rc;
} }
file_handle->hdr_page = &(file_handle->hdr_frame->page); file_header_ = (BPFileHeader *)hdr_frame_->data();
file_handle->bitmap = file_handle->hdr_page->data + BP_FILE_SUB_HDR_SIZE;
file_handle->file_sub_header = (BPFileSubHeader *)file_handle->hdr_page->data;
open_list_[empty_id] = file_handle;
*file_id = empty_id;
LOG_INFO("Successfully open %s. file_id=%d, hdr_frame=%p", file_name, *file_id, file_handle->hdr_frame); LOG_INFO("Successfully open %s. file_desc=%d, hdr_frame=%p", file_name, file_desc_, hdr_frame_);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::close_file(int file_id) RC DiskBufferPool::close_file()
{ {
RC tmp; RC rc = RC::SUCCESS;
if ((tmp = check_file_id(file_id)) != RC::SUCCESS) { if (file_desc_ < 0) {
LOG_ERROR("Failed to close file, due to invalid fileId %d", file_id); return rc;
return tmp;
} }
BPFileHandle *file_handle = open_list_[file_id]; hdr_frame_->pin_count_--;
file_handle->hdr_frame->pin_count--; if ((rc = purge_all_pages()) != RC::SUCCESS) {
if ((tmp = purge_all_pages(file_handle)) != RC::SUCCESS) { hdr_frame_->pin_count_++;
file_handle->hdr_frame->pin_count++; LOG_ERROR("Failed to close %s, due to failed to purge all pages.", file_name_.c_str());
LOG_ERROR("Failed to close file %d:%s, due to failed to purge all pages.", file_id, file_handle->file_name); return rc;
return tmp;
} }
disposed_pages.erase(file_handle->file_desc); disposed_pages.clear();
if (close(file_handle->file_desc) < 0) { if (close(file_desc_) < 0) {
LOG_ERROR("Failed to close fileId:%d, fileName:%s, error:%s", file_id, file_handle->file_name, strerror(errno)); LOG_ERROR("Failed to close fileId:%d, fileName:%s, error:%s", file_desc_, file_name_.c_str(), strerror(errno));
return RC::IOERR_CLOSE; return RC::IOERR_CLOSE;
} }
open_list_[file_id] = nullptr; LOG_INFO("Successfully close file %d:%s.", file_desc_, file_name_.c_str());
LOG_INFO("Successfully close file %d:%s.", file_id, file_handle->file_name); file_desc_ = -1;
delete file_handle;
bp_manager_.close_file(file_name_.c_str());
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::get_this_page(int file_id, PageNum page_num, BPPageHandle *page_handle) RC DiskBufferPool::get_this_page(PageNum page_num, Frame **frame)
{ {
RC tmp; RC rc = RC::SUCCESS;
if ((tmp = check_file_id(file_id)) != RC::SUCCESS) {
LOG_ERROR("Failed to load page %d, due to invalid fileId %d", page_num, file_id);
return tmp;
}
BPFileHandle *file_handle = open_list_[file_id];
if ((tmp = check_page_num(page_num, file_handle)) != RC::SUCCESS) {
LOG_ERROR("Failed to load page %s:%d, due to invalid pageNum.", file_handle->file_name, page_num);
return tmp;
}
Frame *used_match_frame = bp_manager_.get(file_handle->file_desc, page_num); Frame *used_match_frame = frame_manager_.get(file_desc_, page_num);
if (used_match_frame != nullptr) { if (used_match_frame != nullptr) {
page_handle->frame = used_match_frame; used_match_frame->pin_count_++;
page_handle->frame->pin_count++; used_match_frame->acc_time_ = current_time();
page_handle->frame->acc_time = current_time();
page_handle->open = true;
bp_manager_.mark_modified(used_match_frame); frame_manager_.mark_modified(used_match_frame);
*frame = used_match_frame;
return RC::SUCCESS; return RC::SUCCESS;
} }
// Allocate one page and load the data into this page // Allocate one page and load the data into this page
if ((tmp = allocate_page(&(page_handle->frame))) != RC::SUCCESS) { Frame *allocated_frame = nullptr;
LOG_ERROR("Failed to load page %s:%d, due to failed to alloc page.", file_handle->file_name, page_num); if ((rc = allocate_frame(&allocated_frame)) != RC::SUCCESS) {
return tmp; LOG_ERROR("Failed to alloc frame %s:%d, due to failed to alloc page.", file_name_.c_str(), page_num);
} return rc;
page_handle->frame->dirty = false; }
page_handle->frame->file_desc = file_handle->file_desc;
page_handle->frame->pin_count = 1; allocated_frame->dirty_ = false;
page_handle->frame->acc_time = current_time(); allocated_frame->file_desc_ = file_desc_;
if ((tmp = load_page(page_num, file_handle, page_handle->frame)) != RC::SUCCESS) { allocated_frame->pin_count_ = 1;
LOG_ERROR("Failed to load page %s:%d", file_handle->file_name, page_num); allocated_frame->acc_time_ = current_time();
page_handle->frame->pin_count = 0; if ((rc = load_page(page_num, allocated_frame)) != RC::SUCCESS) {
purge_page(page_handle->frame); LOG_ERROR("Failed to load page %s:%d", file_name_.c_str(), page_num);
return tmp; allocated_frame->pin_count_ = 0;
} purge_frame(allocated_frame);
return rc;
page_handle->open = true; }
*frame = allocated_frame;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::allocate_page(int file_id, BPPageHandle *page_handle) RC DiskBufferPool::allocate_page(Frame **frame)
{ {
RC tmp; RC rc = RC::SUCCESS;
if ((tmp = check_file_id(file_id)) != RC::SUCCESS) {
LOG_ERROR("Failed to alloc page, due to invalid fileId %d", file_id);
return tmp;
}
BPFileHandle *file_handle = open_list_[file_id];
int byte = 0, bit = 0; int byte = 0, bit = 0;
if ((file_handle->file_sub_header->allocated_pages) < (file_handle->file_sub_header->page_count)) { if ((file_header_->allocated_pages) < (file_header_->page_count)) {
// There is one free page // There is one free page
for (int i = 0; i < file_handle->file_sub_header->page_count; i++) { for (int i = 0; i < file_header_->page_count; i++) {
byte = i / 8; byte = i / 8;
bit = i % 8; bit = i % 8;
if (((file_handle->bitmap[byte]) & (1 << bit)) == 0) { if (((file_header_->bitmap[byte]) & (1 << bit)) == 0) {
(file_handle->file_sub_header->allocated_pages)++; (file_header_->allocated_pages)++;
file_handle->bitmap[byte] |= (1 << bit); file_header_->bitmap[byte] |= (1 << bit);
// TODO, do we need clean the loaded page's data? // TODO, do we need clean the loaded page's data?
return get_this_page(file_id, i, page_handle); hdr_frame_->mark_dirty();
return get_this_page(i, frame);
} }
} }
} }
if ((tmp = allocate_page(&(page_handle->frame))) != RC::SUCCESS) { Frame *allocated_frame = nullptr;
LOG_ERROR("Failed to allocate page %s, due to no free page.", file_handle->file_name); if ((rc = allocate_frame(&allocated_frame)) != RC::SUCCESS) {
return tmp; LOG_ERROR("Failed to allocate frame %s, due to no free page.", file_name_.c_str());
return rc;
} }
PageNum page_num = file_handle->file_sub_header->page_count; PageNum page_num = file_header_->page_count;
file_handle->file_sub_header->allocated_pages++; file_header_->allocated_pages++;
file_handle->file_sub_header->page_count++; file_header_->page_count++;
byte = page_num / 8; byte = page_num / 8;
bit = page_num % 8; bit = page_num % 8;
file_handle->bitmap[byte] |= (1 << bit); file_header_->bitmap[byte] |= (1 << bit);
file_handle->hdr_frame->dirty = true; hdr_frame_->mark_dirty();
page_handle->frame->dirty = false; allocated_frame->dirty_ = false;
page_handle->frame->file_desc = file_handle->file_desc; allocated_frame->file_desc_ = file_desc_;
page_handle->frame->pin_count = 1; allocated_frame->pin_count_ = 1;
page_handle->frame->acc_time = current_time(); allocated_frame->acc_time_ = current_time();
memset(&(page_handle->frame->page), 0, sizeof(Page)); allocated_frame->clear_page();
page_handle->frame->page.page_num = file_handle->file_sub_header->page_count - 1; allocated_frame->page_.page_num = file_header_->page_count - 1;
// Use flush operation to extension file // Use flush operation to extension file
if ((tmp = flush_page(page_handle->frame)) != RC::SUCCESS) { if ((rc = flush_page(*allocated_frame)) != RC::SUCCESS) {
LOG_WARN("Failed to alloc page %s , due to failed to extend one page.", file_handle->file_name); LOG_WARN("Failed to alloc page %s , due to failed to extend one page.", file_name_.c_str());
// skip return false, delay flush the extended page // skip return false, delay flush the extended page
// return tmp; // return tmp;
} }
page_handle->open = true; *frame = allocated_frame;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::get_page_num(BPPageHandle *page_handle, PageNum *page_num) RC DiskBufferPool::unpin_page(Frame *frame)
{ {
if (!page_handle->open) if (--frame->pin_count_ == 0) {
return RC::BUFFERPOOL_CLOSED; PageNum page_num = frame->page_num();
*page_num = page_handle->frame->page.page_num; auto pages_it = disposed_pages.find(page_num);
return RC::SUCCESS; if (pages_it != disposed_pages.end()) {
} LOG_INFO("Dispose file_desc:%d, page:%d", file_desc_, page_num);
dispose_page(page_num);
RC DiskBufferPool::get_data(BPPageHandle *page_handle, char **data) disposed_pages.erase(pages_it);
{
if (!page_handle->open)
return RC::BUFFERPOOL_CLOSED;
*data = page_handle->frame->page.data;
return RC::SUCCESS;
}
RC DiskBufferPool::mark_dirty(BPPageHandle *page_handle)
{
page_handle->frame->dirty = true;
return RC::SUCCESS;
}
RC DiskBufferPool::unpin_page(BPPageHandle *page_handle)
{
page_handle->open = false;
if (--page_handle->frame->pin_count == 0) {
int file_desc = page_handle->frame->file_desc;
auto it = disposed_pages.find(file_desc);
if (it != disposed_pages.end()) {
BPDisposedPages &disposed_page = it->second;
PageNum page_num = page_handle->frame->page.page_num;
auto pages_it = disposed_page.pages.find(page_num);
if (pages_it != disposed_page.pages.end()) {
LOG_INFO("Dispose file_id:%d, page:%d", disposed_page.file_id, page_num);
dispose_page(disposed_page.file_id, page_num);
disposed_page.pages.erase(pages_it);
}
} }
} }
...@@ -420,256 +274,314 @@ RC DiskBufferPool::unpin_page(BPPageHandle *page_handle) ...@@ -420,256 +274,314 @@ RC DiskBufferPool::unpin_page(BPPageHandle *page_handle)
/** /**
* dispose_page will delete the data of the page of pageNum, free the page both from buffer pool and data file. * dispose_page will delete the data of the page of pageNum, free the page both from buffer pool and data file.
* purge_page will purge the page of pageNum, free the page from buffer pool * purge_page will purge the page of pageNum, free the page from buffer pool
* @param fileID
* @param pageNum
* @return * @return
*/ */
RC DiskBufferPool::dispose_page(int file_id, PageNum page_num) RC DiskBufferPool::dispose_page(PageNum page_num)
{ {
RC rc; RC rc = purge_page(page_num);
if ((rc = check_file_id(file_id)) != RC::SUCCESS) {
LOG_ERROR("Failed to alloc page, due to invalid fileId %d", file_id);
return rc;
}
BPFileHandle *file_handle = open_list_[file_id];
if ((rc = check_page_num(page_num, file_handle)) != RC::SUCCESS) {
LOG_ERROR("Failed to dispose page %s:%d, due to invalid pageNum", file_handle->file_name, page_num);
return rc;
}
rc = purge_page(file_handle, page_num);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_INFO("Dispose page %s:%d later, due to this page is being used", file_handle->file_name, page_num); LOG_INFO("Dispose page %s:%d later, due to this page is being used", file_name_.c_str(), page_num);
auto it = disposed_pages.find(file_handle->file_desc);
if (it == disposed_pages.end()) {
BPDisposedPages disposed_page;
disposed_page.file_id = file_id;
disposed_page.pages.insert(page_num);
disposed_pages.insert(std::pair<int, BPDisposedPages>(file_handle->file_desc, disposed_page));
} else {
BPDisposedPages &disposed_page = it->second;
disposed_page.pages.insert(page_num);
}
disposed_pages.insert(page_num);
return rc; return rc;
} }
file_handle->hdr_frame->dirty = true; hdr_frame_->dirty_ = true;
file_handle->file_sub_header->allocated_pages--; file_header_->allocated_pages--;
// file_handle->pFileSubHeader->pageCount--;
char tmp = 1 << (page_num % 8); char tmp = 1 << (page_num % 8);
file_handle->bitmap[page_num / 8] &= ~tmp; file_header_->bitmap[page_num / 8] &= ~tmp;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::purge_page(int file_id, PageNum page_num) RC DiskBufferPool::purge_frame(Frame *buf)
{ {
RC rc; if (buf->pin_count_ > 0) {
if ((rc = check_file_id(file_id)) != RC::SUCCESS) {
LOG_ERROR("Failed to alloc page, due to invalid fileId %d", file_id);
return rc;
}
BPFileHandle *file_handle = open_list_[file_id];
return purge_page(file_handle, page_num);
}
RC DiskBufferPool::purge_page(Frame *buf)
{
if (buf->pin_count > 0) {
LOG_INFO("Begin to free page %d of %d(file id), but it's pinned, pin_count:%d.", LOG_INFO("Begin to free page %d of %d(file id), but it's pinned, pin_count:%d.",
buf->page.page_num, buf->page_num(), buf->file_desc_, buf->pin_count_);
buf->file_desc,
buf->pin_count);
return RC::LOCKED_UNLOCK; return RC::LOCKED_UNLOCK;
} }
if (buf->dirty) { if (buf->dirty_) {
RC rc = flush_page(buf); RC rc = flush_page(*buf);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to flush page %d of %d(file desc) during purge page.", buf->page.page_num, buf->file_desc); LOG_WARN("Failed to flush page %d of %d(file desc) during purge page.", buf->page_num(), buf->file_desc_);
return rc; return rc;
} }
} }
LOG_DEBUG("Successfully purge frame =%p, page %d of %d(file desc)", buf, buf->page.page_num, buf->file_desc); LOG_DEBUG("Successfully purge frame =%p, page %d of %d(file desc)", buf, buf->page_num(), buf->file_desc_);
bp_manager_.free(buf); frame_manager_.free(buf);
return RC::SUCCESS; return RC::SUCCESS;
} }
/** /**
* dispose_page will delete the data of the page of pageNum * dispose_page will delete the data of the page of pageNum
* force_page will flush the page of pageNum * force_page will flush the page of pageNum
* @param fileHandle
* @param pageNum * @param pageNum
* @return * @return
*/ */
RC DiskBufferPool::purge_page(BPFileHandle *file_handle, PageNum page_num) RC DiskBufferPool::purge_page(PageNum page_num)
{ {
Frame *used_frame = bp_manager_.get(file_handle->file_desc, page_num); Frame *used_frame = frame_manager_.get(file_desc_, page_num);
if (used_frame != nullptr) { if (used_frame != nullptr) {
return purge_page(used_frame); return purge_frame(used_frame);
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::purge_all_pages(int file_id) RC DiskBufferPool::purge_all_pages()
{
RC rc = check_file_id(file_id);
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush pages due to invalid file_id %d", file_id);
return rc;
}
BPFileHandle *file_handle = open_list_[file_id];
return purge_all_pages(file_handle);
}
RC DiskBufferPool::purge_all_pages(BPFileHandle *file_handle)
{ {
std::list<Frame *> used = bp_manager_.find_list(file_handle->file_desc); std::list<Frame *> used = frame_manager_.find_list(file_desc_);
for (std::list<Frame *>::iterator it = used.begin(); it != used.end(); ++it) { for (std::list<Frame *>::iterator it = used.begin(); it != used.end(); ++it) {
Frame *frame = *it; Frame *frame = *it;
if (frame->pin_count > 0) { if (frame->pin_count_ > 0) {
LOG_WARN("The page has been pinned, file_desc:%d, pagenum:%d, pin_count=%d", LOG_WARN("The page has been pinned, file_desc:%d, pagenum:%d, pin_count=%d",
frame->file_desc, frame->page.page_num, frame->pin_count); frame->file_desc_, frame->page_.page_num, frame->pin_count_);
continue; continue;
} }
if (frame->dirty) { if (frame->dirty_) {
RC rc = flush_page(frame); RC rc = flush_page(*frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush all pages' of %s.", file_handle->file_name); LOG_ERROR("Failed to flush all pages' of %s.", file_name_.c_str());
return rc; return rc;
} }
} }
bp_manager_.free(frame); frame_manager_.free(frame);
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::check_all_pages_unpinned(int file_id) RC DiskBufferPool::check_all_pages_unpinned()
{ {
RC rc = check_file_id(file_id); std::list<Frame *> frames = frame_manager_.find_list(file_desc_);
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush pages due to invalid file_id %d", file_id);
return rc;
}
BPFileHandle *file_handle = open_list_[file_id];
std::list<Frame *> frames = bp_manager_.find_list(file_handle->file_desc);
for (auto & frame : frames) { for (auto & frame : frames) {
if (frame->page.page_num == 0 && frame->pin_count > 1) { if (frame->page_num() == BP_HEADER_PAGE && frame->pin_count_ > 1) {
LOG_WARN("This page has been pinned. file id=%d, page num:%d, pin count=%d", LOG_WARN("This page has been pinned. file desc=%d, page num:%d, pin count=%d",
file_id, frame->page.page_num, frame->pin_count); file_desc_, frame->page_num(), frame->pin_count_);
} else if (frame->page.page_num != 0 && frame->pin_count > 0) { } else if (frame->page_num() != BP_HEADER_PAGE && frame->pin_count_ > 0) {
LOG_WARN("This page has been pinned. file id=%d, page num:%d, pin count=%d", LOG_WARN("This page has been pinned. file desc=%d, page num:%d, pin count=%d",
file_id, frame->page.page_num, frame->pin_count); file_desc_, frame->page_num(), frame->pin_count_);
} }
} }
LOG_INFO("all pages have been checked of file id %d", file_id); LOG_INFO("all pages have been checked of file desc %d", file_desc_);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::flush_page(Frame *frame) RC DiskBufferPool::flush_page(Frame &frame)
{ {
// The better way is use mmap the block into memory, // The better way is use mmap the block into memory,
// so it is easier to flush data to file. // so it is easier to flush data to file.
s64_t offset = ((s64_t)frame->page.page_num) * sizeof(Page); Page &page = frame.page_;
if (lseek(frame->file_desc, offset, SEEK_SET) == offset - 1) { s64_t offset = ((s64_t)page.page_num) * sizeof(Page);
LOG_ERROR("Failed to flush page %lld of %d due to failed to seek %s.", offset, frame->file_desc, strerror(errno)); if (lseek(file_desc_, offset, SEEK_SET) == offset - 1) {
LOG_ERROR("Failed to flush page %lld of %d due to failed to seek %s.", offset, file_desc_, strerror(errno));
return RC::IOERR_SEEK; return RC::IOERR_SEEK;
} }
if (write(frame->file_desc, &(frame->page), sizeof(Page)) != sizeof(Page)) { if (write(file_desc_, &page, sizeof(Page)) != sizeof(Page)) {
LOG_ERROR("Failed to flush page %lld of %d due to %s.", offset, frame->file_desc, strerror(errno)); LOG_ERROR("Failed to flush page %lld of %d due to %s.", offset, file_desc_, strerror(errno));
return RC::IOERR_WRITE; return RC::IOERR_WRITE;
} }
frame->dirty = false; frame.dirty_ = false;
LOG_DEBUG("Flush block. file desc=%d, page num=%d", frame->file_desc, frame->page.page_num); LOG_DEBUG("Flush block. file desc=%d, page num=%d", file_desc_, page.page_num);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::allocate_page(Frame **buffer) RC DiskBufferPool::allocate_frame(Frame **buffer)
{ {
Frame *frame = bp_manager_.alloc(); Frame *frame = frame_manager_.alloc();
if (frame != nullptr) { if (frame != nullptr) {
*buffer = frame; *buffer = frame;
return RC::SUCCESS; return RC::SUCCESS;
} }
frame = bp_manager_.begin_purge(); frame = frame_manager_.begin_purge();
if (frame == nullptr) { if (frame == nullptr) {
LOG_ERROR("All pages have been used and pinned."); LOG_ERROR("All pages have been used and pinned.");
return RC::NOMEM; return RC::NOMEM;
} }
if (frame->dirty) { if (frame->dirty_) {
RC rc = flush_page(frame); RC rc = bp_manager_.flush_page(*frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to aclloc block due to failed to flush old block."); LOG_ERROR("Failed to aclloc block due to failed to flush old block.");
return rc; return rc;
} }
} }
bp_manager_.mark_modified(frame); frame_manager_.mark_modified(frame);
*buffer = frame; *buffer = frame;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::check_file_id(int file_id) RC DiskBufferPool::check_page_num(PageNum page_num)
{ {
if (file_id < 0 || file_id >= MAX_OPEN_FILE) { if (page_num >= file_header_->page_count) {
LOG_ERROR("Invalid fileId:%d.", file_id); LOG_ERROR("Invalid pageNum:%d, file's name:%s", page_num, file_name_.c_str());
return RC::BUFFERPOOL_ILLEGAL_FILE_ID; return RC::BUFFERPOOL_INVALID_PAGE_NUM;
} }
if (!open_list_[file_id]) { if ((file_header_->bitmap[page_num / 8] & (1 << (page_num % 8))) == 0) {
LOG_ERROR("Invalid fileId:%d, it is empty.", file_id); LOG_ERROR("Invalid pageNum:%d, file's name:%s", page_num, file_name_.c_str());
return RC::BUFFERPOOL_ILLEGAL_FILE_ID; return RC::BUFFERPOOL_INVALID_PAGE_NUM;
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::get_page_count(int file_id, int *page_count) RC DiskBufferPool::load_page(PageNum page_num, Frame *frame)
{ {
RC rc = RC::SUCCESS; s64_t offset = ((s64_t)page_num) * sizeof(Page);
if ((rc = check_file_id(file_id)) != RC::SUCCESS) { if (lseek(file_desc_, offset, SEEK_SET) == -1) {
return rc; LOG_ERROR("Failed to load page %s:%d, due to failed to lseek:%s.",
file_name_.c_str(), page_num, strerror(errno));
return RC::IOERR_SEEK;
}
if (read(file_desc_, &(frame->page_), sizeof(Page)) != sizeof(Page)) {
LOG_ERROR("Failed to load page %s:%d, due to failed to read data:%s.",
file_name_.c_str(), page_num, strerror(errno));
return RC::IOERR_READ;
} }
*page_count = open_list_[file_id]->file_sub_header->page_count;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::check_page_num(PageNum page_num, BPFileHandle *file_handle) RC DiskBufferPool::get_page_count(int *page_count)
{ {
if (page_num >= file_handle->file_sub_header->page_count) { *page_count = file_header_->allocated_pages;
LOG_ERROR("Invalid pageNum:%d, file's name:%s", page_num, file_handle->file_name); return RC::SUCCESS;
return RC::BUFFERPOOL_INVALID_PAGE_NUM; }
int DiskBufferPool::file_desc() const
{
return file_desc_;
}
////////////////////////////////////////////////////////////////////////////////
BufferPoolManager::BufferPoolManager()
{
frame_manager_.init(true/*dynamic*/, MEM_POOL_ITEM_NUM);
}
BufferPoolManager::~BufferPoolManager()
{
std::unordered_map<std::string, DiskBufferPool *> tmp_bps;
tmp_bps.swap(buffer_pools_);
for (auto &iter : tmp_bps) {
delete iter.second;
} }
if ((file_handle->bitmap[page_num / 8] & (1 << (page_num % 8))) == 0) { }
LOG_ERROR("Invalid pageNum:%d, file's name:%s", page_num, file_handle->file_name);
return RC::BUFFERPOOL_INVALID_PAGE_NUM; RC BufferPoolManager::create_file(const char *file_name)
{
int fd = open(file_name, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
if (fd < 0) {
LOG_ERROR("Failed to create %s, due to %s.", file_name, strerror(errno));
return RC::SCHEMA_DB_EXIST;
}
close(fd);
/**
* Here don't care about the failure
*/
fd = open(file_name, O_RDWR);
if (fd < 0) {
LOG_ERROR("Failed to open for readwrite %s, due to %s.", file_name, strerror(errno));
return RC::IOERR_ACCESS;
}
Page page;
memset(&page, 0, sizeof(Page));
BPFileHeader *file_header = (BPFileHeader *)page.data;
file_header->allocated_pages = 1;
file_header->page_count = 1;
char *bitmap = file_header->bitmap;
bitmap[0] |= 0x01;
if (lseek(fd, 0, SEEK_SET) == -1) {
LOG_ERROR("Failed to seek file %s to position 0, due to %s .", file_name, strerror(errno));
close(fd);
return RC::IOERR_SEEK;
} }
if (write(fd, (char *)&page, sizeof(Page)) != sizeof(Page)) {
LOG_ERROR("Failed to write header to file %s, due to %s.", file_name, strerror(errno));
close(fd);
return RC::IOERR_WRITE;
}
close(fd);
LOG_INFO("Successfully create %s.", file_name);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC DiskBufferPool::load_page(PageNum page_num, BPFileHandle *file_handle, Frame *frame) RC BufferPoolManager::open_file(const char *_file_name, DiskBufferPool *& _bp)
{ {
s64_t offset = ((s64_t)page_num) * sizeof(Page); std::string file_name(_file_name);
if (lseek(file_handle->file_desc, offset, SEEK_SET) == -1) {
LOG_ERROR( if (buffer_pools_.find(file_name) != buffer_pools_.end()) {
"Failed to load page %s:%d, due to failed to lseek:%s.", file_handle->file_name, page_num, strerror(errno)); LOG_WARN("file already opened. file name=%s", _file_name);
return RC::BUFFERPOOL_OPEN;
}
return RC::IOERR_SEEK; DiskBufferPool *bp = new DiskBufferPool(*this, frame_manager_);
RC rc = bp->open_file(_file_name);
if (rc != RC::SUCCESS) {
LOG_WARN("failed to open file name");
delete bp;
return rc;
} }
if (read(file_handle->file_desc, &(frame->page), sizeof(Page)) != sizeof(Page)) {
LOG_ERROR( buffer_pools_.insert(std::pair<std::string, DiskBufferPool *>(file_name, bp));
"Failed to load page %s:%d, due to failed to read data:%s.", file_handle->file_name, page_num, strerror(errno)); fd_buffer_pools_.insert(std::pair<int, DiskBufferPool *>(bp->file_desc(), bp));
return RC::IOERR_READ; _bp = bp;
return RC::SUCCESS;
}
RC BufferPoolManager::close_file(const char *_file_name)
{
std::string file_name(_file_name);
auto iter = buffer_pools_.find(file_name);
if (iter == buffer_pools_.end()) {
LOG_WARN("file has not opened: %s", _file_name);
return RC::INTERNAL;
} }
int fd = iter->second->file_desc();
fd_buffer_pools_.erase(fd);
DiskBufferPool *bp = iter->second;
buffer_pools_.erase(iter);
delete bp;
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BufferPoolManager::flush_page(Frame &frame)
{
int fd = frame.file_desc();
auto iter = fd_buffer_pools_.find(fd);
if (iter == fd_buffer_pools_.end()) {
LOG_WARN("unknown buffer pool of fd %d", fd);
return RC::INTERNAL;
}
DiskBufferPool *bp = iter->second;
return bp->flush_page(frame);
}
static BufferPoolManager *default_bpm = nullptr;
void BufferPoolManager::set_instance(BufferPoolManager *bpm)
{
if (default_bpm != nullptr && bpm != nullptr) {
LOG_ERROR("default buffer pool manager has been setted");
abort();
}
default_bpm = bpm;
}
BufferPoolManager &BufferPoolManager::instance()
{
return *default_bpm;
}
...@@ -14,19 +14,23 @@ See the Mulan PSL v2 for more details. */ ...@@ -14,19 +14,23 @@ See the Mulan PSL v2 for more details. */
#ifndef __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_ #ifndef __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_
#define __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_ #define __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <time.h> #include <time.h>
#include <string>
#include <unordered_map>
#include "rc.h" #include "rc.h"
#include "common/mm/mem_pool.h" #include "common/mm/mem_pool.h"
typedef int PageNum; typedef int32_t PageNum;
class BufferPoolManager;
class DiskBufferPool;
// //
#define BP_INVALID_PAGE_NUM (-1) #define BP_INVALID_PAGE_NUM (-1)
...@@ -34,73 +38,82 @@ typedef int PageNum; ...@@ -34,73 +38,82 @@ typedef int PageNum;
#define BP_PAGE_DATA_SIZE (BP_PAGE_SIZE - sizeof(PageNum)) #define BP_PAGE_DATA_SIZE (BP_PAGE_SIZE - sizeof(PageNum))
#define BP_FILE_SUB_HDR_SIZE (sizeof(BPFileSubHeader)) #define BP_FILE_SUB_HDR_SIZE (sizeof(BPFileSubHeader))
#define BP_BUFFER_SIZE 256 #define BP_BUFFER_SIZE 256
#define MAX_OPEN_FILE 1024
typedef struct { struct Page {
PageNum page_num; PageNum page_num;
char data[BP_PAGE_DATA_SIZE]; char data[BP_PAGE_DATA_SIZE];
} Page; };
// sizeof(Page) should be equal to BP_PAGE_SIZE // sizeof(Page) should be equal to BP_PAGE_SIZE
typedef struct { /**
PageNum page_count; * BufferPool的文件第一个页面,存放一些元数据信息,包括了后面每页的分配信息。
int allocated_pages; * TODO 1. 当前的做法,只能分配比较少的页面,你可以扩展一下,支持更多的页面或无限多的页面吗?
} BPFileSubHeader; * 可以参考Linux ext(n)和Windows NTFS等文件系统
* 2. 当前使用bitmap存放页面分配情况,但是这种方法在页面非常多的时候,查找空闲页面的
typedef struct { * 效率非常低,你有办法优化吗?
int file_id; */
std::set<PageNum> pages; struct BPFileHeader {
} BPDisposedPages; int32_t page_count; //! 当前文件一共有多少个页面
int32_t allocated_pages; //! 已经分配了多少个页面
typedef struct Frame_ { char bitmap[0]; //! 页面分配位图, 第0个页面(就是当前页面),总是1
bool dirty; };
unsigned int pin_count;
unsigned long acc_time;
int file_desc;
Page page;
bool can_purge() class Frame
{
public:
void clear_page()
{ {
return pin_count <= 0; memset(&page_, 0, sizeof(page_));
} }
} Frame;
typedef struct BPPageHandle { PageNum page_num() const
BPPageHandle() : open(false), frame(nullptr) {
{} return page_.page_num;
}
PageNum page_num() const { void set_page_num(PageNum page_num)
return frame->page.page_num; {
page_.page_num = page_num;
} }
/**
* 标记指定页面为“脏”页。如果修改了页面的内容,则应调用此函数,
* 以便该页面被淘汰出缓冲区时系统将新的页面数据写入磁盘文件
*/
void mark_dirty() { void mark_dirty() {
this->frame->dirty = true; dirty_ = true;
} }
char *data() { char *data() {
return this->frame->page.data; return page_.data;
} }
bool open;
Frame *frame;
} BPPageHandle;
class BPFileHandle { int file_desc() const
public: {
BPFileHandle(); return file_desc_;
~BPFileHandle(); }
public: void set_file_desc(int fd)
bool bopen; {
const char *file_name; file_desc_ = fd;
int file_desc; }
Frame *hdr_frame; bool can_purge()
Page *hdr_page; {
char *bitmap; return pin_count_ <= 0;
BPFileSubHeader *file_sub_header; }
private:
friend class DiskBufferPool;
bool dirty_ = false;
unsigned int pin_count_ = 0;
unsigned long acc_time_ = 0;
int file_desc_ = -1;
Page page_;
}; };
class BPManager : public common::MemPoolSimple<Frame> { class BPFrameManager : public common::MemPoolSimple<Frame> {
public: public:
BPManager(const char *tag); BPFrameManager(const char *tag);
Frame *get(int file_desc, PageNum page_num); Frame *get(int file_desc, PageNum page_num);
...@@ -111,26 +124,7 @@ public: ...@@ -111,26 +124,7 @@ public:
class DiskBufferPool { class DiskBufferPool {
public: public:
static DiskBufferPool *mk_instance() DiskBufferPool(BufferPoolManager &bp_manager, BPFrameManager &frame_manager);
{
return new DiskBufferPool();
}
static void set_pool_num(int pool_num)
{
if (pool_num > 0) {
POOL_NUM = pool_num;
LOG_INFO("Successfully set POOL_NUM as %d", pool_num);
} else {
LOG_INFO("Invalid input argument pool_num:%d", pool_num);
}
}
static const int get_pool_num()
{
return POOL_NUM;
}
~DiskBufferPool(); ~DiskBufferPool();
/** /**
...@@ -142,53 +136,36 @@ public: ...@@ -142,53 +136,36 @@ public:
* 根据文件名打开一个分页文件,返回文件ID * 根据文件名打开一个分页文件,返回文件ID
* @return * @return
*/ */
RC open_file(const char *file_name, int *file_id); RC open_file(const char *file_name);
/** /**
* 关闭fileID对应的分页文件 * 关闭分页文件
*/ */
RC close_file(int file_id); RC close_file();
/** /**
* 根据文件ID和页号获取指定页面到缓冲区,返回页面句柄指针。 * 根据文件ID和页号获取指定页面到缓冲区,返回页面句柄指针。
* @return * @return
*/ */
RC get_this_page(int file_id, PageNum page_num, BPPageHandle *page_handle); RC get_this_page(PageNum page_num, Frame **frame);
/** /**
* 在指定文件中分配一个新的页面,并将其放入缓冲区,返回页面句柄指针。 * 在指定文件中分配一个新的页面,并将其放入缓冲区,返回页面句柄指针。
* 分配页面时,如果文件中有空闲页,就直接分配一个空闲页; * 分配页面时,如果文件中有空闲页,就直接分配一个空闲页;
* 如果文件中没有空闲页,则扩展文件规模来增加新的空闲页。 * 如果文件中没有空闲页,则扩展文件规模来增加新的空闲页。
*/ */
RC allocate_page(int file_id, BPPageHandle *page_handle); RC allocate_page(Frame **frame);
/**
* 根据页面句柄指针返回对应的页面号
*/
RC get_page_num(BPPageHandle *page_handle, PageNum *page_num);
/**
* 根据页面句柄指针返回对应的数据区指针
*/
RC get_data(BPPageHandle *page_handle, char **data);
/** /**
* 比purge_page多一个动作, 在磁盘上将对应的页数据删掉。 * 比purge_page多一个动作, 在磁盘上将对应的页数据删掉。
*/ */
RC dispose_page(int file_id, PageNum page_num); RC dispose_page(PageNum page_num);
/** /**
* 释放指定文件关联的页的内存, 如果已经脏, 则刷到磁盘,除了pinned page * 释放指定文件关联的页的内存, 如果已经脏, 则刷到磁盘,除了pinned page
* @param file_handle
* @param page_num 如果不指定page_num 将刷新所有页
*/ */
RC purge_page(int file_id, PageNum page_num); RC purge_page(PageNum page_num);
RC purge_all_pages();
/**
* 标记指定页面为“脏”页。如果修改了页面的内容,则应调用此函数,
* 以便该页面被淘汰出缓冲区时系统将新的页面数据写入磁盘文件
*/
RC mark_dirty(BPPageHandle *page_handle);
/** /**
* 此函数用于解除pageHandle对应页面的驻留缓冲区限制。 * 此函数用于解除pageHandle对应页面的驻留缓冲区限制。
...@@ -196,44 +173,66 @@ public: ...@@ -196,44 +173,66 @@ public:
* 该页面被设置为驻留缓冲区状态,以防止其在处理过程中被置换出去, * 该页面被设置为驻留缓冲区状态,以防止其在处理过程中被置换出去,
* 因此在该页面使用完之后应调用此函数解除该限制,使得该页面此后可以正常地被淘汰出缓冲区 * 因此在该页面使用完之后应调用此函数解除该限制,使得该页面此后可以正常地被淘汰出缓冲区
*/ */
RC unpin_page(BPPageHandle *page_handle); RC unpin_page(Frame *frame);
/** /**
* 获取文件的总页数 * 获取文件的总页数
*/ */
RC get_page_count(int file_id, int *page_count); RC get_page_count(int *page_count);
RC check_all_pages_unpinned();
RC purge_all_pages(int file_id); int file_desc() const;
RC check_all_pages_unpinned(int file_id); /**
* 如果页面是脏的,就将数据刷新到磁盘
*/
RC flush_page(Frame &frame);
protected: protected:
RC allocate_page(Frame **buf); RC allocate_frame(Frame **buf);
/** /**
* 刷新指定文件关联的所有脏页到磁盘,除了pinned page * 刷新指定页面到磁盘(flush),并且释放关联的Frame
* @param file_handle
* @param page_num 如果不指定page_num 将刷新所有页
*/ */
RC purge_page(BPFileHandle *file_handle, PageNum page_num); RC purge_frame(Frame *used_frame);
RC purge_page(Frame *used_frame); RC check_page_num(PageNum page_num);
RC purge_all_pages(BPFileHandle *file_handle);
RC check_file_id(int file_id);
RC check_page_num(PageNum page_num, BPFileHandle *file_handle);
RC load_page(PageNum page_num, BPFileHandle *file_handle, Frame *frame);
RC flush_page(Frame *frame);
private: /**
DiskBufferPool(); * 加载指定页面的数据到内存中
*/
RC load_page(PageNum page_num, Frame *frame);
private: private:
BPManager bp_manager_; BufferPoolManager &bp_manager_;
BPFileHandle *open_list_[MAX_OPEN_FILE] = {nullptr}; BPFrameManager & frame_manager_;
std::map<int, BPDisposedPages> disposed_pages; std::string file_name_;
int file_desc_ = -1;
static int POOL_NUM; Frame * hdr_frame_ = nullptr;
BPFileHeader * file_header_ = nullptr;
std::set<PageNum> disposed_pages;
}; };
DiskBufferPool *theGlobalDiskBufferPool(); class BufferPoolManager
{
public:
BufferPoolManager();
~BufferPoolManager();
RC create_file(const char *file_name);
RC open_file(const char *file_name, DiskBufferPool *&bp);
RC close_file(const char *file_name);
RC flush_page(Frame &frame);
public:
static void set_instance(BufferPoolManager *bpm);
static BufferPoolManager &instance();
private:
BPFrameManager frame_manager_{"BufPool"};
std::unordered_map<std::string, DiskBufferPool *> buffer_pools_;
std::unordered_map<int, DiskBufferPool *> fd_buffer_pools_;
};
#endif //__OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_ #endif //__OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_
...@@ -38,8 +38,8 @@ int calc_leaf_page_capacity(int attr_length) ...@@ -38,8 +38,8 @@ int calc_leaf_page_capacity(int attr_length)
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
IndexNodeHandler::IndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle) IndexNodeHandler::IndexNodeHandler(const IndexFileHeader &header, Frame *frame)
: header_(header), page_num_(page_handle.page_num()), node_((IndexNode *)page_handle.data()) : header_(header), page_num_(frame->page_num()), node_((IndexNode *)frame->data())
{} {}
bool IndexNodeHandler::is_leaf() const bool IndexNodeHandler::is_leaf() const
...@@ -122,8 +122,8 @@ bool IndexNodeHandler::validate() const ...@@ -122,8 +122,8 @@ bool IndexNodeHandler::validate() const
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
LeafIndexNodeHandler::LeafIndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle) LeafIndexNodeHandler::LeafIndexNodeHandler(const IndexFileHeader &header, Frame *frame)
: IndexNodeHandler(header, page_handle), leaf_node_((LeafIndexNode *)page_handle.data()) : IndexNodeHandler(header, frame), leaf_node_((LeafIndexNode *)frame->data())
{} {}
void LeafIndexNodeHandler::init_empty() void LeafIndexNodeHandler::init_empty()
...@@ -224,7 +224,7 @@ int LeafIndexNodeHandler::remove(const char *key, const KeyComparator &comparato ...@@ -224,7 +224,7 @@ int LeafIndexNodeHandler::remove(const char *key, const KeyComparator &comparato
return 0; return 0;
} }
RC LeafIndexNodeHandler::move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id) RC LeafIndexNodeHandler::move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp)
{ {
const int size = this->size(); const int size = this->size();
const int move_index = size / 2; const int move_index = size / 2;
...@@ -234,7 +234,7 @@ RC LeafIndexNodeHandler::move_half_to(LeafIndexNodeHandler &other, DiskBufferPoo ...@@ -234,7 +234,7 @@ RC LeafIndexNodeHandler::move_half_to(LeafIndexNodeHandler &other, DiskBufferPoo
this->increase_size(- ( size - move_index)); this->increase_size(- ( size - move_index));
return RC::SUCCESS; return RC::SUCCESS;
} }
RC LeafIndexNodeHandler::move_first_to_end(LeafIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id) RC LeafIndexNodeHandler::move_first_to_end(LeafIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool)
{ {
other.append(__item_at(0)); other.append(__item_at(0));
...@@ -245,7 +245,7 @@ RC LeafIndexNodeHandler::move_first_to_end(LeafIndexNodeHandler &other, DiskBuff ...@@ -245,7 +245,7 @@ RC LeafIndexNodeHandler::move_first_to_end(LeafIndexNodeHandler &other, DiskBuff
return RC::SUCCESS; return RC::SUCCESS;
} }
RC LeafIndexNodeHandler::move_last_to_front(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id) RC LeafIndexNodeHandler::move_last_to_front(LeafIndexNodeHandler &other, DiskBufferPool *bp)
{ {
other.preappend(__item_at(size() - 1)); other.preappend(__item_at(size() - 1));
...@@ -255,7 +255,7 @@ RC LeafIndexNodeHandler::move_last_to_front(LeafIndexNodeHandler &other, DiskBuf ...@@ -255,7 +255,7 @@ RC LeafIndexNodeHandler::move_last_to_front(LeafIndexNodeHandler &other, DiskBuf
/** /**
* move all items to left page * move all items to left page
*/ */
RC LeafIndexNodeHandler::move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id) RC LeafIndexNodeHandler::move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp)
{ {
memcpy(other.__item_at(other.size()), this->__item_at(0), this->size() * item_size()); memcpy(other.__item_at(other.size()), this->__item_at(0), this->size() * item_size());
other.increase_size(this->size()); other.increase_size(this->size());
...@@ -265,17 +265,17 @@ RC LeafIndexNodeHandler::move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp ...@@ -265,17 +265,17 @@ RC LeafIndexNodeHandler::move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp
PageNum next_right_page_num = this->next_page(); PageNum next_right_page_num = this->next_page();
if (next_right_page_num != BP_INVALID_PAGE_NUM) { if (next_right_page_num != BP_INVALID_PAGE_NUM) {
BPPageHandle next_right_page_handle; Frame *next_right_frame;
RC rc = bp->get_this_page(file_id, next_right_page_num, &next_right_page_handle); RC rc = bp->get_this_page(next_right_page_num, &next_right_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next right page. page number:%d. rc=%d:%s", next_right_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next right page. page number:%d. rc=%d:%s", next_right_page_num, rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler next_right_node(header_, next_right_page_handle); LeafIndexNodeHandler next_right_node(header_, next_right_frame);
next_right_node.set_prev_page(other.page_num()); next_right_node.set_prev_page(other.page_num());
next_right_page_handle.mark_dirty(); next_right_frame->mark_dirty();
bp->unpin_page(&next_right_page_handle); bp->unpin_page(next_right_frame);
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -322,7 +322,7 @@ std::string to_string(const LeafIndexNodeHandler &handler, const KeyPrinter &pri ...@@ -322,7 +322,7 @@ std::string to_string(const LeafIndexNodeHandler &handler, const KeyPrinter &pri
return ss.str(); return ss.str();
} }
bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferPool *bp, int file_id) const bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferPool *bp) const
{ {
bool result = IndexNodeHandler::validate(); bool result = IndexNodeHandler::validate();
if (false == result) { if (false == result) {
...@@ -343,20 +343,20 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP ...@@ -343,20 +343,20 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP
return true; return true;
} }
BPPageHandle parent_page_handle; Frame *parent_frame;
RC rc = bp->get_this_page(file_id, parent_page_num, &parent_page_handle); RC rc = bp->get_this_page(parent_page_num, &parent_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch parent page. page num=%d, rc=%d:%s", LOG_WARN("failed to fetch parent page. page num=%d, rc=%d:%s",
parent_page_num, rc, strrc(rc)); parent_page_num, rc, strrc(rc));
return false; return false;
} }
InternalIndexNodeHandler parent_node(header_, parent_page_handle); InternalIndexNodeHandler parent_node(header_, parent_frame);
int index_in_parent = parent_node.value_index(this->page_num()); int index_in_parent = parent_node.value_index(this->page_num());
if (index_in_parent < 0) { if (index_in_parent < 0) {
LOG_WARN("invalid leaf node. cannot find index in parent. this page num=%d, parent page num=%d", LOG_WARN("invalid leaf node. cannot find index in parent. this page num=%d, parent page num=%d",
this->page_num(), parent_page_num); this->page_num(), parent_page_num);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
...@@ -366,7 +366,7 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP ...@@ -366,7 +366,7 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP
LOG_WARN("invalid leaf node. first item should be greate than or equal to parent item. " \ LOG_WARN("invalid leaf node. first item should be greate than or equal to parent item. " \
"this page num=%d, parent page num=%d, index in parent=%d", "this page num=%d, parent page num=%d, index in parent=%d",
this->page_num(), parent_node.page_num(), index_in_parent); this->page_num(), parent_node.page_num(), index_in_parent);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
} }
...@@ -377,17 +377,17 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP ...@@ -377,17 +377,17 @@ bool LeafIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferP
LOG_WARN("invalid leaf node. last item should be less than the item at the first after item in parent." \ LOG_WARN("invalid leaf node. last item should be less than the item at the first after item in parent." \
"this page num=%d, parent page num=%d, parent item to compare=%d", "this page num=%d, parent page num=%d, parent item to compare=%d",
this->page_num(), parent_node.page_num(), index_in_parent + 1); this->page_num(), parent_node.page_num(), index_in_parent + 1);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
} }
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return true; return true;
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
InternalIndexNodeHandler::InternalIndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle) InternalIndexNodeHandler::InternalIndexNodeHandler(const IndexFileHeader &header, Frame *frame)
: IndexNodeHandler(header, page_handle), internal_node_((InternalIndexNode *)page_handle.data()) : IndexNodeHandler(header, frame), internal_node_((InternalIndexNode *)frame->data())
{} {}
std::string to_string(const InternalIndexNodeHandler &node, const KeyPrinter &printer) std::string to_string(const InternalIndexNodeHandler &node, const KeyPrinter &printer)
...@@ -436,11 +436,11 @@ void InternalIndexNodeHandler::insert(const char *key, PageNum page_num, const K ...@@ -436,11 +436,11 @@ void InternalIndexNodeHandler::insert(const char *key, PageNum page_num, const K
increase_size(1); increase_size(1);
} }
RC InternalIndexNodeHandler::move_half_to(InternalIndexNodeHandler &other, DiskBufferPool *bp, int file_id) RC InternalIndexNodeHandler::move_half_to(InternalIndexNodeHandler &other, DiskBufferPool *bp)
{ {
const int size = this->size(); const int size = this->size();
const int move_index = size / 2; const int move_index = size / 2;
RC rc = other.copy_from(this->__item_at(move_index), size - move_index, bp, file_id); RC rc = other.copy_from(this->__item_at(move_index), size - move_index, bp);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to copy item to new node. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to copy item to new node. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
...@@ -538,9 +538,9 @@ void InternalIndexNodeHandler::remove(int index) ...@@ -538,9 +538,9 @@ void InternalIndexNodeHandler::remove(int index)
increase_size(-1); increase_size(-1);
} }
RC InternalIndexNodeHandler::move_to(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id) RC InternalIndexNodeHandler::move_to(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool)
{ {
RC rc = other.copy_from(__item_at(0), size(), disk_buffer_pool, file_id); RC rc = other.copy_from(__item_at(0), size(), disk_buffer_pool);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to copy items to other node. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to copy items to other node. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
...@@ -550,9 +550,9 @@ RC InternalIndexNodeHandler::move_to(InternalIndexNodeHandler &other, DiskBuffer ...@@ -550,9 +550,9 @@ RC InternalIndexNodeHandler::move_to(InternalIndexNodeHandler &other, DiskBuffer
return RC::SUCCESS; return RC::SUCCESS;
} }
RC InternalIndexNodeHandler::move_first_to_end(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id) RC InternalIndexNodeHandler::move_first_to_end(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool)
{ {
RC rc = other.append(__item_at(0), disk_buffer_pool, file_id); RC rc = other.append(__item_at(0), disk_buffer_pool);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to append item to others."); LOG_WARN("failed to append item to others.");
return rc; return rc;
...@@ -565,9 +565,9 @@ RC InternalIndexNodeHandler::move_first_to_end(InternalIndexNodeHandler &other, ...@@ -565,9 +565,9 @@ RC InternalIndexNodeHandler::move_first_to_end(InternalIndexNodeHandler &other,
return rc; return rc;
} }
RC InternalIndexNodeHandler::move_last_to_front(InternalIndexNodeHandler &other, DiskBufferPool *bp, int file_id) RC InternalIndexNodeHandler::move_last_to_front(InternalIndexNodeHandler &other, DiskBufferPool *bp)
{ {
RC rc = other.preappend(__item_at(size() - 1), bp, file_id); RC rc = other.preappend(__item_at(size() - 1), bp);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to preappend to others"); LOG_WARN("failed to preappend to others");
return rc; return rc;
...@@ -579,50 +579,50 @@ RC InternalIndexNodeHandler::move_last_to_front(InternalIndexNodeHandler &other, ...@@ -579,50 +579,50 @@ RC InternalIndexNodeHandler::move_last_to_front(InternalIndexNodeHandler &other,
/** /**
* copy items from other node to self's right * copy items from other node to self's right
*/ */
RC InternalIndexNodeHandler::copy_from(const char *items, int num, DiskBufferPool *disk_buffer_pool, int file_id) RC InternalIndexNodeHandler::copy_from(const char *items, int num, DiskBufferPool *disk_buffer_pool)
{ {
memcpy(__item_at(this->size()), items, num * item_size()); memcpy(__item_at(this->size()), items, num * item_size());
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
PageNum this_page_num = this->page_num(); PageNum this_page_num = this->page_num();
BPPageHandle page_handle; Frame *frame = nullptr;
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
const PageNum page_num = *(const PageNum *)((items + i * item_size()) + key_size()); const PageNum page_num = *(const PageNum *)((items + i * item_size()) + key_size());
rc = disk_buffer_pool->get_this_page(file_id, page_num, &page_handle); rc = disk_buffer_pool->get_this_page(page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to set child's page num. child page num:%d, this page num=%d, rc=%d:%s", LOG_WARN("failed to set child's page num. child page num:%d, this page num=%d, rc=%d:%s",
page_num, this_page_num, rc, strrc(rc)); page_num, this_page_num, rc, strrc(rc));
return rc; return rc;
} }
IndexNodeHandler child_node(header_, page_handle); IndexNodeHandler child_node(header_, frame);
child_node.set_parent_page_num(this_page_num); child_node.set_parent_page_num(this_page_num);
page_handle.mark_dirty(); frame->mark_dirty();
disk_buffer_pool->unpin_page(&page_handle); disk_buffer_pool->unpin_page(frame);
} }
increase_size(num); increase_size(num);
return rc; return rc;
} }
RC InternalIndexNodeHandler::append(const char *item, DiskBufferPool *bp, int file_id) RC InternalIndexNodeHandler::append(const char *item, DiskBufferPool *bp)
{ {
return this->copy_from(item, 1, bp, file_id); return this->copy_from(item, 1, bp);
} }
RC InternalIndexNodeHandler::preappend(const char *item, DiskBufferPool *bp, int file_id) RC InternalIndexNodeHandler::preappend(const char *item, DiskBufferPool *bp)
{ {
PageNum child_page_num = *(PageNum *)(item + key_size()); PageNum child_page_num = *(PageNum *)(item + key_size());
BPPageHandle page_handle; Frame *frame = nullptr;
RC rc = bp->get_this_page(file_id, child_page_num, &page_handle); RC rc = bp->get_this_page(child_page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch child page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to fetch child page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
IndexNodeHandler child_node(header_, page_handle); IndexNodeHandler child_node(header_, frame);
child_node.set_parent_page_num(this->page_num()); child_node.set_parent_page_num(this->page_num());
page_handle.mark_dirty(); frame->mark_dirty();
bp->unpin_page(&page_handle); bp->unpin_page(frame);
if (this->size() > 0) { if (this->size() > 0) {
memmove(__item_at(1), __item_at(0), this->size() * item_size()); memmove(__item_at(1), __item_at(0), this->size() * item_size());
...@@ -658,7 +658,7 @@ int InternalIndexNodeHandler::item_size() const ...@@ -658,7 +658,7 @@ int InternalIndexNodeHandler::item_size() const
return key_size() + this->value_size(); return key_size() + this->value_size();
} }
bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferPool *bp, int file_id) const bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBufferPool *bp) const
{ {
bool result = IndexNodeHandler::validate(); bool result = IndexNodeHandler::validate();
if (false == result) { if (false == result) {
...@@ -679,19 +679,19 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf ...@@ -679,19 +679,19 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf
if (page_num < 0) { if (page_num < 0) {
LOG_WARN("this page num=%d, got invalid child page. page num=%d", this->page_num(), page_num); LOG_WARN("this page num=%d, got invalid child page. page num=%d", this->page_num(), page_num);
} else { } else {
BPPageHandle child_page_handle; Frame *child_frame;
RC rc = bp->get_this_page(file_id, page_num, &child_page_handle); RC rc = bp->get_this_page(page_num, &child_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch child page while validate internal page. page num=%d, rc=%d:%s", LOG_WARN("failed to fetch child page while validate internal page. page num=%d, rc=%d:%s",
page_num, rc, strrc(rc)); page_num, rc, strrc(rc));
} else { } else {
IndexNodeHandler child_node(header_, child_page_handle); IndexNodeHandler child_node(header_, child_frame);
if (child_node.parent_page_num() != this->page_num()) { if (child_node.parent_page_num() != this->page_num()) {
LOG_WARN("child's parent page num is invalid. child page num=%d, parent page num=%d, this page num=%d", LOG_WARN("child's parent page num is invalid. child page num=%d, parent page num=%d, this page num=%d",
child_node.page_num(), child_node.parent_page_num(), this->page_num()); child_node.page_num(), child_node.parent_page_num(), this->page_num());
result = false; result = false;
} }
bp->unpin_page(&child_page_handle); bp->unpin_page(child_frame);
} }
} }
} }
...@@ -705,19 +705,19 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf ...@@ -705,19 +705,19 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf
return result; return result;
} }
BPPageHandle parent_page_handle; Frame *parent_frame;
RC rc = bp->get_this_page(file_id, parent_page_num, &parent_page_handle); RC rc = bp->get_this_page(parent_page_num, &parent_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch parent page. page num=%d, rc=%d:%s", parent_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch parent page. page num=%d, rc=%d:%s", parent_page_num, rc, strrc(rc));
return false; return false;
} }
InternalIndexNodeHandler parent_node(header_, parent_page_handle); InternalIndexNodeHandler parent_node(header_, parent_frame);
int index_in_parent = parent_node.value_index(this->page_num()); int index_in_parent = parent_node.value_index(this->page_num());
if (index_in_parent < 0) { if (index_in_parent < 0) {
LOG_WARN("invalid internal node. cannot find index in parent. this page num=%d, parent page num=%d", LOG_WARN("invalid internal node. cannot find index in parent. this page num=%d, parent page num=%d",
this->page_num(), parent_page_num); this->page_num(), parent_page_num);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
...@@ -727,7 +727,7 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf ...@@ -727,7 +727,7 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf
LOG_WARN("invalid internal node. the second item should be greate than or equal to parent item. " \ LOG_WARN("invalid internal node. the second item should be greate than or equal to parent item. " \
"this page num=%d, parent page num=%d, index in parent=%d", "this page num=%d, parent page num=%d, index in parent=%d",
this->page_num(), parent_node.page_num(), index_in_parent); this->page_num(), parent_node.page_num(), index_in_parent);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
} }
...@@ -738,11 +738,11 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf ...@@ -738,11 +738,11 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf
LOG_WARN("invalid internal node. last item should be less than the item at the first after item in parent." \ LOG_WARN("invalid internal node. last item should be less than the item at the first after item in parent." \
"this page num=%d, parent page num=%d, parent item to compare=%d", "this page num=%d, parent page num=%d, parent item to compare=%d",
this->page_num(), parent_node.page_num(), index_in_parent + 1); this->page_num(), parent_node.page_num(), index_in_parent + 1);
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return false; return false;
} }
} }
bp->unpin_page(&parent_page_handle); bp->unpin_page(parent_frame);
return result; return result;
} }
...@@ -751,40 +751,40 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf ...@@ -751,40 +751,40 @@ bool InternalIndexNodeHandler::validate(const KeyComparator &comparator, DiskBuf
RC BplusTreeHandler::sync() RC BplusTreeHandler::sync()
{ {
return disk_buffer_pool_->purge_all_pages(file_id_); return disk_buffer_pool_->purge_all_pages();
} }
RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_length, RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_length,
int internal_max_size /* = -1*/, int leaf_max_size /* = -1 */) int internal_max_size /* = -1*/, int leaf_max_size /* = -1 */)
{ {
DiskBufferPool *disk_buffer_pool = theGlobalDiskBufferPool(); BufferPoolManager &bpm = BufferPoolManager::instance();
RC rc = disk_buffer_pool->create_file(file_name); RC rc = bpm.create_file(file_name);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to create file. file name=%s, rc=%d:%s", file_name, rc, strrc(rc)); LOG_WARN("Failed to create file. file name=%s, rc=%d:%s", file_name, rc, strrc(rc));
return rc; return rc;
} }
LOG_INFO("Successfully create index file:%s", file_name); LOG_INFO("Successfully create index file:%s", file_name);
int file_id; DiskBufferPool *bp = nullptr;
rc = disk_buffer_pool->open_file(file_name, &file_id); rc = bpm.open_file(file_name, bp);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to open file. file name=%s, rc=%d:%s", file_name, rc, strrc(rc)); LOG_WARN("Failed to open file. file name=%s, rc=%d:%s", file_name, rc, strrc(rc));
return rc; return rc;
} }
LOG_INFO("Successfully open index file %s.", file_name); LOG_INFO("Successfully open index file %s.", file_name);
BPPageHandle header_page_handle; Frame *header_frame;
rc = disk_buffer_pool->allocate_page(file_id, &header_page_handle); rc = bp->allocate_page(&header_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to allocate header page for bplus tree. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to allocate header page for bplus tree. rc=%d:%s", rc, strrc(rc));
disk_buffer_pool->close_file(file_id); bpm.close_file(file_name);
return rc; return rc;
} }
if (header_page_handle.page_num() != FIRST_INDEX_PAGE) { if (header_frame->page_num() != FIRST_INDEX_PAGE) {
LOG_WARN("header page num should be %d but got %d. is it a new file : %s", LOG_WARN("header page num should be %d but got %d. is it a new file : %s",
FIRST_INDEX_PAGE, header_page_handle.page_num(), file_name); FIRST_INDEX_PAGE, header_frame->page_num(), file_name);
disk_buffer_pool->close_file(file_id); bpm.close_file(file_name);
return RC::INTERNAL; return RC::INTERNAL;
} }
...@@ -794,7 +794,8 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_ ...@@ -794,7 +794,8 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_
if (leaf_max_size < 0) { if (leaf_max_size < 0) {
leaf_max_size = calc_leaf_page_capacity(attr_length); leaf_max_size = calc_leaf_page_capacity(attr_length);
} }
char *pdata = header_page_handle.data();
char *pdata = header_frame->data();
IndexFileHeader *file_header = (IndexFileHeader *)pdata; IndexFileHeader *file_header = (IndexFileHeader *)pdata;
file_header->attr_length = attr_length; file_header->attr_length = attr_length;
file_header->key_length = attr_length + sizeof(RID); file_header->key_length = attr_length + sizeof(RID);
...@@ -803,14 +804,13 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_ ...@@ -803,14 +804,13 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_
file_header->leaf_max_size = leaf_max_size; file_header->leaf_max_size = leaf_max_size;
file_header->root_page = BP_INVALID_PAGE_NUM; file_header->root_page = BP_INVALID_PAGE_NUM;
header_page_handle.mark_dirty(); header_frame->mark_dirty();
disk_buffer_pool->unpin_page(&header_page_handle);
disk_buffer_pool_ = disk_buffer_pool; disk_buffer_pool_ = bp;
file_id_ = file_id;
memcpy(&file_header_, pdata, sizeof(file_header_)); memcpy(&file_header_, pdata, sizeof(file_header_));
header_dirty_ = false; header_dirty_ = false;
bp->unpin_page(header_frame);
mem_pool_item_ = new common::MemPoolItem(file_name); mem_pool_item_ = new common::MemPoolItem(file_name);
if (mem_pool_item_->init(file_header->key_length) < 0) { if (mem_pool_item_->init(file_header->key_length) < 0) {
...@@ -827,32 +827,31 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_ ...@@ -827,32 +827,31 @@ RC BplusTreeHandler::create(const char *file_name, AttrType attr_type, int attr_
RC BplusTreeHandler::open(const char *file_name) RC BplusTreeHandler::open(const char *file_name)
{ {
if (file_id_ >= 0) { if (disk_buffer_pool_ != nullptr) {
LOG_WARN("%s has been opened before index.open.", file_name); LOG_WARN("%s has been opened before index.open.", file_name);
return RC::RECORD_OPENNED; return RC::RECORD_OPENNED;
} }
DiskBufferPool *disk_buffer_pool = theGlobalDiskBufferPool(); BufferPoolManager &bpm = BufferPoolManager::instance();
int file_id = 0; DiskBufferPool *disk_buffer_pool;
RC rc = disk_buffer_pool->open_file(file_name, &file_id); RC rc = bpm.open_file(file_name, disk_buffer_pool);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to open file name=%s, rc=%d:%s", file_name, rc, strrc(rc)); LOG_WARN("Failed to open file name=%s, rc=%d:%s", file_name, rc, strrc(rc));
return rc; return rc;
} }
BPPageHandle page_handle; Frame *frame;
rc = disk_buffer_pool->get_this_page(file_id, FIRST_INDEX_PAGE, &page_handle); rc = disk_buffer_pool->get_this_page(FIRST_INDEX_PAGE, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to get first page file name=%s, rc=%d:%s", file_name, rc, strrc(rc)); LOG_WARN("Failed to get first page file name=%s, rc=%d:%s", file_name, rc, strrc(rc));
disk_buffer_pool_->close_file(file_id); bpm.close_file(file_name);
return rc; return rc;
} }
char *pdata = page_handle.data(); char *pdata = frame->data();
memcpy(&file_header_, pdata, sizeof(IndexFileHeader)); memcpy(&file_header_, pdata, sizeof(IndexFileHeader));
header_dirty_ = false; header_dirty_ = false;
disk_buffer_pool_ = disk_buffer_pool; disk_buffer_pool_ = disk_buffer_pool;
file_id_ = file_id;
mem_pool_item_ = new common::MemPoolItem(file_name); mem_pool_item_ = new common::MemPoolItem(file_name);
if (mem_pool_item_->init(file_header_.key_length) < 0) { if (mem_pool_item_->init(file_header_.key_length) < 0) {
...@@ -862,19 +861,19 @@ RC BplusTreeHandler::open(const char *file_name) ...@@ -862,19 +861,19 @@ RC BplusTreeHandler::open(const char *file_name)
} }
// close old page_handle // close old page_handle
disk_buffer_pool->unpin_page(&page_handle); disk_buffer_pool->unpin_page(frame);
key_comparator_.init(file_header_.attr_type, file_header_.attr_length); key_comparator_.init(file_header_.attr_type, file_header_.attr_length);
key_printer_.init(file_header_.attr_type, file_header_.attr_length);
LOG_INFO("Successfully open index %s", file_name); LOG_INFO("Successfully open index %s", file_name);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::close() RC BplusTreeHandler::close()
{ {
if (file_id_ != -1) { if (disk_buffer_pool_ != nullptr) {
disk_buffer_pool_->close_file(file_id_); disk_buffer_pool_->close_file(); // TODO
file_id_ = -1;
delete mem_pool_item_; delete mem_pool_item_;
mem_pool_item_ = nullptr; mem_pool_item_ = nullptr;
...@@ -884,52 +883,52 @@ RC BplusTreeHandler::close() ...@@ -884,52 +883,52 @@ RC BplusTreeHandler::close()
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::print_leaf(BPPageHandle &page_handle) RC BplusTreeHandler::print_leaf(Frame *frame)
{ {
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
LOG_INFO("leaf node: %s", to_string(leaf_node, key_printer_).c_str()); LOG_INFO("leaf node: %s", to_string(leaf_node, key_printer_).c_str());
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::print_internal_node_recursive(BPPageHandle &page_handle) RC BplusTreeHandler::print_internal_node_recursive(Frame *frame)
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
LOG_INFO("bplus tree. file header: %s", file_header_.to_string().c_str()); LOG_INFO("bplus tree. file header: %s", file_header_.to_string().c_str());
InternalIndexNodeHandler internal_node(file_header_, page_handle); InternalIndexNodeHandler internal_node(file_header_, frame);
LOG_INFO("internal node: %s", to_string(internal_node, key_printer_).c_str()); LOG_INFO("internal node: %s", to_string(internal_node, key_printer_).c_str());
int node_size = internal_node.size(); int node_size = internal_node.size();
for (int i = 0; i < node_size; i++) { for (int i = 0; i < node_size; i++) {
PageNum page_num = internal_node.value_at(i); PageNum page_num = internal_node.value_at(i);
BPPageHandle child_page_handle; Frame *child_frame;
rc = disk_buffer_pool_->get_this_page(file_id_, page_num, &child_page_handle); rc = disk_buffer_pool_->get_this_page(page_num, &child_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch child page. page id=%d, rc=%d:%s", page_num, rc, strrc(rc)); LOG_WARN("failed to fetch child page. page id=%d, rc=%d:%s", page_num, rc, strrc(rc));
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return rc; return rc;
} }
IndexNodeHandler node(file_header_, child_page_handle); IndexNodeHandler node(file_header_, child_frame);
if (node.is_leaf()) { if (node.is_leaf()) {
rc = print_leaf(child_page_handle); rc = print_leaf(child_frame);
} else { } else {
rc = print_internal_node_recursive(child_page_handle); rc = print_internal_node_recursive(child_frame);
} }
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to print node. page id=%d, rc=%d:%s", child_page_handle.page_num(), rc, strrc(rc)); LOG_WARN("failed to print node. page id=%d, rc=%d:%s", child_frame->page_num(), rc, strrc(rc));
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return rc; return rc;
} }
} }
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::print_tree() RC BplusTreeHandler::print_tree()
{ {
if (file_id_ < 0) { if (disk_buffer_pool_ == nullptr) {
LOG_WARN("Index hasn't been created or opened, fail to print"); LOG_WARN("Index hasn't been created or opened, fail to print");
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -938,19 +937,19 @@ RC BplusTreeHandler::print_tree() ...@@ -938,19 +937,19 @@ RC BplusTreeHandler::print_tree()
return RC::SUCCESS; return RC::SUCCESS;
} }
BPPageHandle page_handle; Frame *frame;
PageNum page_num = file_header_.root_page; PageNum page_num = file_header_.root_page;
RC rc = disk_buffer_pool_->get_this_page(file_id_, page_num, &page_handle); RC rc = disk_buffer_pool_->get_this_page(page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch page. page id=%d, rc=%d:%s", page_num, rc, strrc(rc)); LOG_WARN("failed to fetch page. page id=%d, rc=%d:%s", page_num, rc, strrc(rc));
return rc; return rc;
} }
IndexNodeHandler node(file_header_, page_handle); IndexNodeHandler node(file_header_, frame);
if (node.is_leaf()) { if (node.is_leaf()) {
rc = print_leaf(page_handle); rc = print_leaf(frame);
} else { } else {
rc = print_internal_node_recursive(page_handle); rc = print_internal_node_recursive(frame);
} }
return rc; return rc;
} }
...@@ -962,26 +961,26 @@ RC BplusTreeHandler::print_leafs() ...@@ -962,26 +961,26 @@ RC BplusTreeHandler::print_leafs()
return RC::SUCCESS; return RC::SUCCESS;
} }
BPPageHandle page_handle; Frame *frame;
RC rc = left_most_page(page_handle); RC rc = left_most_page(frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to get left most page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to get left most page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
while (page_handle.page_num() != BP_INVALID_PAGE_NUM) { while (frame->page_num() != BP_INVALID_PAGE_NUM) {
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
LOG_INFO("leaf info: %s", to_string(leaf_node, key_printer_).c_str()); LOG_INFO("leaf info: %s", to_string(leaf_node, key_printer_).c_str());
PageNum next_page_num = leaf_node.next_page(); PageNum next_page_num = leaf_node.next_page();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
if (next_page_num == BP_INVALID_PAGE_NUM) { if (next_page_num == BP_INVALID_PAGE_NUM) {
break; break;
} }
rc = disk_buffer_pool_->get_this_page(file_id_, next_page_num, &page_handle); rc = disk_buffer_pool_->get_this_page(next_page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to get next page. page id=%d, rc=%d:%s", next_page_num, rc, strrc(rc)); LOG_WARN("failed to get next page. page id=%d, rc=%d:%s", next_page_num, rc, strrc(rc));
return rc; return rc;
...@@ -990,31 +989,31 @@ RC BplusTreeHandler::print_leafs() ...@@ -990,31 +989,31 @@ RC BplusTreeHandler::print_leafs()
return rc; return rc;
} }
bool BplusTreeHandler::validate_node_recursive(BPPageHandle &page_handle) bool BplusTreeHandler::validate_node_recursive(Frame *frame)
{ {
bool result = true; bool result = true;
IndexNodeHandler node(file_header_, page_handle); IndexNodeHandler node(file_header_, frame);
if (node.is_leaf()) { if (node.is_leaf()) {
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
result = leaf_node.validate(key_comparator_, disk_buffer_pool_, file_id_); result = leaf_node.validate(key_comparator_, disk_buffer_pool_);
} else { } else {
InternalIndexNodeHandler internal_node(file_header_, page_handle); InternalIndexNodeHandler internal_node(file_header_, frame);
result = internal_node.validate(key_comparator_, disk_buffer_pool_, file_id_); result = internal_node.validate(key_comparator_, disk_buffer_pool_);
for (int i = 0; result && i < internal_node.size(); i++) { for (int i = 0; result && i < internal_node.size(); i++) {
PageNum page_num = internal_node.value_at(i); PageNum page_num = internal_node.value_at(i);
BPPageHandle child_page_handle; Frame *child_frame;
RC rc = disk_buffer_pool_->get_this_page(file_id_, page_num, &child_page_handle); RC rc = disk_buffer_pool_->get_this_page(page_num, &child_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch child page.page id=%d, rc=%d:%s", page_num, rc, strrc(rc)); LOG_WARN("failed to fetch child page.page id=%d, rc=%d:%s", page_num, rc, strrc(rc));
result = false; result = false;
break; break;
} }
result = validate_node_recursive(child_page_handle); result = validate_node_recursive(child_frame);
} }
} }
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return result; return result;
} }
...@@ -1024,8 +1023,8 @@ bool BplusTreeHandler::validate_leaf_link() ...@@ -1024,8 +1023,8 @@ bool BplusTreeHandler::validate_leaf_link()
return true; return true;
} }
BPPageHandle page_handle; Frame *frame;
RC rc = left_most_page(page_handle); RC rc = left_most_page(frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch left most page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to fetch left most page. rc=%d:%s", rc, strrc(rc));
return false; return false;
...@@ -1033,31 +1032,31 @@ bool BplusTreeHandler::validate_leaf_link() ...@@ -1033,31 +1032,31 @@ bool BplusTreeHandler::validate_leaf_link()
PageNum prev_page_num = BP_INVALID_PAGE_NUM; PageNum prev_page_num = BP_INVALID_PAGE_NUM;
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
if (leaf_node.prev_page() != prev_page_num) { if (leaf_node.prev_page() != prev_page_num) {
LOG_WARN("invalid page. current_page_num=%d, prev page num should be %d but got %d", LOG_WARN("invalid page. current_page_num=%d, prev page num should be %d but got %d",
page_handle.page_num(), prev_page_num, leaf_node.prev_page()); frame->page_num(), prev_page_num, leaf_node.prev_page());
return false; return false;
} }
PageNum next_page_num = leaf_node.next_page(); PageNum next_page_num = leaf_node.next_page();
prev_page_num = page_handle.page_num(); prev_page_num = frame->page_num();
char *prev_key = (char *)mem_pool_item_->alloc(); char *prev_key = (char *)mem_pool_item_->alloc();
memcpy(prev_key, leaf_node.key_at(leaf_node.size() - 1), file_header_.key_length); memcpy(prev_key, leaf_node.key_at(leaf_node.size() - 1), file_header_.key_length);
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
bool result = true; bool result = true;
while (result && next_page_num != BP_INVALID_PAGE_NUM) { while (result && next_page_num != BP_INVALID_PAGE_NUM) {
rc = disk_buffer_pool_->get_this_page(file_id_, next_page_num, &page_handle); rc = disk_buffer_pool_->get_this_page(next_page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc));
return false; return false;
} }
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
if (leaf_node.prev_page() != prev_page_num) { if (leaf_node.prev_page() != prev_page_num) {
LOG_WARN("invalid page. current_page_num=%d, prev page num should be %d but got %d", LOG_WARN("invalid page. current_page_num=%d, prev page num should be %d but got %d",
page_handle.page_num(), prev_page_num, leaf_node.prev_page()); frame->page_num(), prev_page_num, leaf_node.prev_page());
result = false; result = false;
} }
if (key_comparator_(prev_key, leaf_node.key_at(0)) >= 0) { if (key_comparator_(prev_key, leaf_node.key_at(0)) >= 0) {
...@@ -1067,8 +1066,8 @@ bool BplusTreeHandler::validate_leaf_link() ...@@ -1067,8 +1066,8 @@ bool BplusTreeHandler::validate_leaf_link()
next_page_num = leaf_node.next_page(); next_page_num = leaf_node.next_page();
memcpy(prev_key, leaf_node.key_at(leaf_node.size() - 1), file_header_.key_length); memcpy(prev_key, leaf_node.key_at(leaf_node.size() - 1), file_header_.key_length);
prev_page_num = page_handle.page_num(); prev_page_num = frame->page_num();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
} }
free_key(prev_key); free_key(prev_key);
...@@ -1082,14 +1081,14 @@ bool BplusTreeHandler::validate_tree() ...@@ -1082,14 +1081,14 @@ bool BplusTreeHandler::validate_tree()
return true; return true;
} }
BPPageHandle page_handle; Frame *frame;
RC rc = disk_buffer_pool_->get_this_page(file_id_, file_header_.root_page, &page_handle); RC rc = disk_buffer_pool_->get_this_page(file_header_.root_page, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch root page. page id=%d, rc=%d:%s", file_header_.root_page, rc, strrc(rc)); LOG_WARN("failed to fetch root page. page id=%d, rc=%d:%s", file_header_.root_page, rc, strrc(rc));
return rc; return rc;
} }
if (!validate_node_recursive(page_handle) || !validate_leaf_link()) { if (!validate_node_recursive(frame) || !validate_leaf_link()) {
LOG_WARN("Current B+ Tree is invalid"); LOG_WARN("Current B+ Tree is invalid");
print_tree(); print_tree();
return false; return false;
...@@ -1104,68 +1103,68 @@ bool BplusTreeHandler::is_empty() const ...@@ -1104,68 +1103,68 @@ bool BplusTreeHandler::is_empty() const
return file_header_.root_page == BP_INVALID_PAGE_NUM; return file_header_.root_page == BP_INVALID_PAGE_NUM;
} }
RC BplusTreeHandler::find_leaf(const char *key, BPPageHandle &page_handle) RC BplusTreeHandler::find_leaf(const char *key, Frame *&frame)
{ {
return find_leaf_internal( return find_leaf_internal(
[&](InternalIndexNodeHandler &internal_node) { [&](InternalIndexNodeHandler &internal_node) {
return internal_node.value_at(internal_node.lookup(key_comparator_, key)); return internal_node.value_at(internal_node.lookup(key_comparator_, key));
}, },
page_handle); frame);
} }
RC BplusTreeHandler::left_most_page(BPPageHandle &page_handle) RC BplusTreeHandler::left_most_page(Frame *&frame)
{ {
return find_leaf_internal( return find_leaf_internal(
[&](InternalIndexNodeHandler &internal_node) { [&](InternalIndexNodeHandler &internal_node) {
return internal_node.value_at(0); return internal_node.value_at(0);
}, },
page_handle frame
); );
} }
RC BplusTreeHandler::right_most_page(BPPageHandle &page_handle) RC BplusTreeHandler::right_most_page(Frame *&frame)
{ {
return find_leaf_internal( return find_leaf_internal(
[&](InternalIndexNodeHandler &internal_node) { [&](InternalIndexNodeHandler &internal_node) {
return internal_node.value_at(internal_node.size() - 1); return internal_node.value_at(internal_node.size() - 1);
}, },
page_handle frame
); );
} }
RC BplusTreeHandler::find_leaf_internal(const std::function<PageNum(InternalIndexNodeHandler &)> &child_page_getter, RC BplusTreeHandler::find_leaf_internal(const std::function<PageNum(InternalIndexNodeHandler &)> &child_page_getter,
BPPageHandle &page_handle) Frame *&frame)
{ {
if (is_empty()) { if (is_empty()) {
return RC::EMPTY; return RC::EMPTY;
} }
RC rc = disk_buffer_pool_->get_this_page(file_id_, file_header_.root_page, &page_handle); RC rc = disk_buffer_pool_->get_this_page(file_header_.root_page, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch root page. page id=%d, rc=%d:%s", file_header_.root_page, rc, strrc(rc)); LOG_WARN("failed to fetch root page. page id=%d, rc=%d:%s", file_header_.root_page, rc, strrc(rc));
return rc; return rc;
} }
IndexNode *node = (IndexNode *)page_handle.data(); IndexNode *node = (IndexNode *)frame->data();
while (false == node->is_leaf) { while (false == node->is_leaf) {
InternalIndexNodeHandler internal_node(file_header_, page_handle); InternalIndexNodeHandler internal_node(file_header_, frame);
PageNum page_num = child_page_getter(internal_node); PageNum page_num = child_page_getter(internal_node);
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
rc = disk_buffer_pool_->get_this_page(file_id_, page_num, &page_handle); rc = disk_buffer_pool_->get_this_page(page_num, &frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to load page file_id:%d, page_num:%d", file_id_, page_num); LOG_WARN("Failed to load page page_num:%d", page_num);
return rc; return rc;
} }
node = (IndexNode *)page_handle.data(); node = (IndexNode *)frame->data();
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::insert_entry_into_leaf_node(BPPageHandle &page_handle, const char *key, const RID *rid) RC BplusTreeHandler::insert_entry_into_leaf_node(Frame *frame, const char *key, const RID *rid)
{ {
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
bool exists = false; bool exists = false;
int insert_position = leaf_node.lookup(key_comparator_, key, &exists); int insert_position = leaf_node.lookup(key_comparator_, key, &exists);
if (exists) { if (exists) {
...@@ -1175,36 +1174,36 @@ RC BplusTreeHandler::insert_entry_into_leaf_node(BPPageHandle &page_handle, cons ...@@ -1175,36 +1174,36 @@ RC BplusTreeHandler::insert_entry_into_leaf_node(BPPageHandle &page_handle, cons
if (leaf_node.size() < leaf_node.max_size()) { if (leaf_node.size() < leaf_node.max_size()) {
leaf_node.insert(insert_position, key, (const char *)rid); leaf_node.insert(insert_position, key, (const char *)rid);
page_handle.mark_dirty(); frame->mark_dirty();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
BPPageHandle new_page_handle; Frame * new_frame = nullptr;
RC rc = split<LeafIndexNodeHandler>(page_handle, new_page_handle); RC rc = split<LeafIndexNodeHandler>(frame, new_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to split leaf node. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to split leaf node. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler new_index_node(file_header_, new_page_handle); LeafIndexNodeHandler new_index_node(file_header_, new_frame);
new_index_node.set_prev_page(page_handle.page_num()); new_index_node.set_prev_page(frame->page_num());
new_index_node.set_next_page(leaf_node.next_page()); new_index_node.set_next_page(leaf_node.next_page());
new_index_node.set_parent_page_num(leaf_node.parent_page_num()); new_index_node.set_parent_page_num(leaf_node.parent_page_num());
leaf_node.set_next_page(new_page_handle.page_num()); leaf_node.set_next_page(new_frame->page_num());
PageNum next_page_num = new_index_node.next_page(); PageNum next_page_num = new_index_node.next_page();
if (next_page_num != BP_INVALID_PAGE_NUM) { if (next_page_num != BP_INVALID_PAGE_NUM) {
BPPageHandle next_page_handle; Frame * next_frame;
rc = disk_buffer_pool_->get_this_page(file_id_, next_page_num, &next_page_handle); rc = disk_buffer_pool_->get_this_page(next_page_num, &next_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler next_node(file_header_, next_page_handle); LeafIndexNodeHandler next_node(file_header_, next_frame);
next_node.set_prev_page(new_page_handle.page_num()); next_node.set_prev_page(new_frame->page_num());
disk_buffer_pool_->unpin_page(&next_page_handle); disk_buffer_pool_->unpin_page(next_frame);
} }
if (insert_position < leaf_node.size()) { if (insert_position < leaf_node.size()) {
...@@ -1213,94 +1212,94 @@ RC BplusTreeHandler::insert_entry_into_leaf_node(BPPageHandle &page_handle, cons ...@@ -1213,94 +1212,94 @@ RC BplusTreeHandler::insert_entry_into_leaf_node(BPPageHandle &page_handle, cons
new_index_node.insert(insert_position - leaf_node.size(), key, (const char *)rid); new_index_node.insert(insert_position - leaf_node.size(), key, (const char *)rid);
} }
return insert_entry_into_parent(page_handle, new_page_handle, new_index_node.key_at(0)); return insert_entry_into_parent(frame, new_frame, new_index_node.key_at(0));
} }
RC BplusTreeHandler::insert_entry_into_parent(BPPageHandle &page_handle, BPPageHandle &new_page_handle, const char *key) RC BplusTreeHandler::insert_entry_into_parent(Frame *frame, Frame *new_frame, const char *key)
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
IndexNodeHandler node_handler(file_header_, page_handle); IndexNodeHandler node_handler(file_header_, frame);
IndexNodeHandler new_node_handler(file_header_, new_page_handle); IndexNodeHandler new_node_handler(file_header_, new_frame);
PageNum parent_page_num = node_handler.parent_page_num(); PageNum parent_page_num = node_handler.parent_page_num();
if (parent_page_num == BP_INVALID_PAGE_NUM) { if (parent_page_num == BP_INVALID_PAGE_NUM) {
// create new root page // create new root page
BPPageHandle root_page; Frame *root_frame;
rc = disk_buffer_pool_->allocate_page(file_id_, &root_page); rc = disk_buffer_pool_->allocate_page(&root_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to allocate new root page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to allocate new root page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
InternalIndexNodeHandler root_node(file_header_, root_page); InternalIndexNodeHandler root_node(file_header_, root_frame);
root_node.init_empty(); root_node.init_empty();
root_node.create_new_root(page_handle.page_num(), key, new_page_handle.page_num()); root_node.create_new_root(frame->page_num(), key, new_frame->page_num());
node_handler.set_parent_page_num(root_page.page_num()); node_handler.set_parent_page_num(root_frame->page_num());
new_node_handler.set_parent_page_num(root_page.page_num()); new_node_handler.set_parent_page_num(root_frame->page_num());
page_handle.mark_dirty(); frame->mark_dirty();
new_page_handle.mark_dirty(); new_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&new_page_handle); disk_buffer_pool_->unpin_page(new_frame);
file_header_.root_page = root_page.page_num(); file_header_.root_page = root_frame->page_num();
update_root_page_num(); // TODO update_root_page_num(); // TODO
root_page.mark_dirty(); root_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&root_page); disk_buffer_pool_->unpin_page(root_frame);
return RC::SUCCESS; return RC::SUCCESS;
} else { } else {
BPPageHandle parent_page_handle; Frame *parent_frame;
rc = disk_buffer_pool_->get_this_page(file_id_, parent_page_num, &parent_page_handle); rc = disk_buffer_pool_->get_this_page(parent_page_num, &parent_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to insert entry into leaf. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to insert entry into leaf. rc=%d:%s", rc, strrc(rc));
// should do more things to recover // should do more things to recover
return rc; return rc;
} }
InternalIndexNodeHandler node(file_header_, parent_page_handle); InternalIndexNodeHandler node(file_header_, parent_frame);
/// current node is not in full mode, insert the entry and return /// current node is not in full mode, insert the entry and return
if (node.size() < node.max_size()) { if (node.size() < node.max_size()) {
node.insert(key, new_page_handle.page_num(), key_comparator_); node.insert(key, new_frame->page_num(), key_comparator_);
new_node_handler.set_parent_page_num(parent_page_num); new_node_handler.set_parent_page_num(parent_page_num);
page_handle.mark_dirty(); frame->mark_dirty();
new_page_handle.mark_dirty(); new_frame->mark_dirty();
parent_page_handle.mark_dirty(); parent_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&new_page_handle); disk_buffer_pool_->unpin_page(new_frame);
disk_buffer_pool_->unpin_page(&parent_page_handle); disk_buffer_pool_->unpin_page(parent_frame);
} else { } else {
// we should split the node and insert the entry and then insert new entry to current node's parent // we should split the node and insert the entry and then insert new entry to current node's parent
BPPageHandle new_parent_page_handle; Frame * new_parent_frame;
rc = split<InternalIndexNodeHandler>(parent_page_handle, new_parent_page_handle); rc = split<InternalIndexNodeHandler>(parent_frame, new_parent_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to split internal node. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to split internal node. rc=%d:%s", rc, strrc(rc));
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&new_page_handle); disk_buffer_pool_->unpin_page(new_frame);
disk_buffer_pool_->unpin_page(&parent_page_handle); disk_buffer_pool_->unpin_page(parent_frame);
} else { } else {
// insert into left or right ? decide by key compare result // insert into left or right ? decide by key compare result
InternalIndexNodeHandler new_node(file_header_, new_parent_page_handle); InternalIndexNodeHandler new_node(file_header_, new_parent_frame);
if (key_comparator_(key, new_node.key_at(0)) > 0) { if (key_comparator_(key, new_node.key_at(0)) > 0) {
new_node.insert(key, new_page_handle.page_num(), key_comparator_); new_node.insert(key, new_frame->page_num(), key_comparator_);
new_node_handler.set_parent_page_num(new_node.page_num()); new_node_handler.set_parent_page_num(new_node.page_num());
} else { } else {
node.insert(key, new_page_handle.page_num(), key_comparator_); node.insert(key, new_frame->page_num(), key_comparator_);
new_node_handler.set_parent_page_num(node.page_num()); new_node_handler.set_parent_page_num(node.page_num());
} }
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&new_page_handle); disk_buffer_pool_->unpin_page(new_frame);
rc = insert_entry_into_parent(parent_page_handle, new_parent_page_handle, new_node.key_at(0)); rc = insert_entry_into_parent(parent_frame, new_parent_frame, new_node.key_at(0));
} }
} }
} }
...@@ -1314,9 +1313,9 @@ RC BplusTreeHandler::insert_entry_into_parent(BPPageHandle &page_handle, BPPageH ...@@ -1314,9 +1313,9 @@ RC BplusTreeHandler::insert_entry_into_parent(BPPageHandle &page_handle, BPPageH
* @param intert_position the intert position of new key * @param intert_position the intert position of new key
*/ */
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC BplusTreeHandler::split(BPPageHandle &page_handle, BPPageHandle &new_page_handle) RC BplusTreeHandler::split(Frame *frame, Frame *&new_frame)
{ {
IndexNodeHandlerType old_node(file_header_, page_handle); IndexNodeHandlerType old_node(file_header_, frame);
char *new_parent_key = (char *)mem_pool_item_->alloc(); char *new_parent_key = (char *)mem_pool_item_->alloc();
if (new_parent_key == nullptr) { if (new_parent_key == nullptr) {
...@@ -1325,36 +1324,36 @@ RC BplusTreeHandler::split(BPPageHandle &page_handle, BPPageHandle &new_page_han ...@@ -1325,36 +1324,36 @@ RC BplusTreeHandler::split(BPPageHandle &page_handle, BPPageHandle &new_page_han
} }
// add a new node // add a new node
RC rc = disk_buffer_pool_->allocate_page(file_id_, &new_page_handle); RC rc = disk_buffer_pool_->allocate_page(&new_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to split index page due to failed to allocate page, file_id:%d. rc=%d:%s", file_id_, rc, strrc(rc)); LOG_WARN("Failed to split index page due to failed to allocate page, rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
IndexNodeHandlerType new_node(file_header_, new_page_handle); IndexNodeHandlerType new_node(file_header_, new_frame);
new_node.init_empty(); new_node.init_empty();
new_node.set_parent_page_num(old_node.parent_page_num()); new_node.set_parent_page_num(old_node.parent_page_num());
old_node.move_half_to(new_node, disk_buffer_pool_, file_id_); old_node.move_half_to(new_node, disk_buffer_pool_);
page_handle.mark_dirty(); frame->mark_dirty();
new_page_handle.mark_dirty(); new_frame->mark_dirty();
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::update_root_page_num() RC BplusTreeHandler::update_root_page_num()
{ {
BPPageHandle header_page_handle; Frame * header_frame;
RC rc = disk_buffer_pool_->get_this_page(file_id_, FIRST_INDEX_PAGE, &header_page_handle); RC rc = disk_buffer_pool_->get_this_page(FIRST_INDEX_PAGE, &header_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch header page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to fetch header page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
IndexFileHeader *header = (IndexFileHeader *)header_page_handle.data(); IndexFileHeader *header = (IndexFileHeader *)header_frame->data();
header->root_page = file_header_.root_page; header->root_page = file_header_.root_page;
header_page_handle.mark_dirty(); header_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&header_page_handle); disk_buffer_pool_->unpin_page(header_frame);
return rc; return rc;
} }
...@@ -1368,19 +1367,19 @@ RC BplusTreeHandler::create_new_tree(const char *key, const RID *rid) ...@@ -1368,19 +1367,19 @@ RC BplusTreeHandler::create_new_tree(const char *key, const RID *rid)
return rc; return rc;
} }
BPPageHandle page_handle; Frame *frame;
rc = disk_buffer_pool_->allocate_page(file_id_, &page_handle); rc = disk_buffer_pool_->allocate_page(&frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to allocate root page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to allocate root page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler leaf_node(file_header_, page_handle); LeafIndexNodeHandler leaf_node(file_header_, frame);
leaf_node.init_empty(); leaf_node.init_empty();
leaf_node.insert(0, key, (const char *)rid); leaf_node.insert(0, key, (const char *)rid);
file_header_.root_page = page_handle.page_num(); file_header_.root_page = frame->page_num();
page_handle.mark_dirty(); frame->mark_dirty();
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
rc = update_root_page_num(); rc = update_root_page_num();
// disk_buffer_pool_->check_all_pages_unpinned(file_id_); // disk_buffer_pool_->check_all_pages_unpinned(file_id_);
...@@ -1391,7 +1390,7 @@ char *BplusTreeHandler::make_key(const char *user_key, const RID &rid) ...@@ -1391,7 +1390,7 @@ char *BplusTreeHandler::make_key(const char *user_key, const RID &rid)
{ {
char *key = (char *)mem_pool_item_->alloc(); char *key = (char *)mem_pool_item_->alloc();
if (key == nullptr) { if (key == nullptr) {
LOG_WARN("Failed to alloc memory for key. file_id:%d", file_id_); LOG_WARN("Failed to alloc memory for key.");
return nullptr; return nullptr;
} }
memcpy(key, user_key, file_header_.attr_length); memcpy(key, user_key, file_header_.attr_length);
...@@ -1406,11 +1405,6 @@ void BplusTreeHandler::free_key(char *key) ...@@ -1406,11 +1405,6 @@ void BplusTreeHandler::free_key(char *key)
RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid) RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
{ {
if (file_id_ < 0) {
LOG_WARN("Index isn't ready!");
return RC::RECORD_CLOSED;
}
if (user_key == nullptr || rid == nullptr) { if (user_key == nullptr || rid == nullptr) {
LOG_WARN("Invalid arguments, key is empty or rid is empty"); LOG_WARN("Invalid arguments, key is empty or rid is empty");
return RC::INVALID_ARGUMENT; return RC::INVALID_ARGUMENT;
...@@ -1418,7 +1412,7 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid) ...@@ -1418,7 +1412,7 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
char *key = make_key(user_key, *rid); char *key = make_key(user_key, *rid);
if (key == nullptr) { if (key == nullptr) {
LOG_WARN("Failed to alloc memory for key. file_id:%d", file_id_); LOG_WARN("Failed to alloc memory for key.");
return RC::NOMEM; return RC::NOMEM;
} }
...@@ -1426,18 +1420,18 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid) ...@@ -1426,18 +1420,18 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
return create_new_tree(key, rid); return create_new_tree(key, rid);
} }
BPPageHandle page_handle; Frame *frame;
RC rc = find_leaf(key, page_handle); RC rc = find_leaf(key, frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to find leaf file_id:%d, %s. rc=%d:%s", file_id_, rid->to_string().c_str(), rc, strrc(rc)); LOG_WARN("Failed to find leaf %s. rc=%d:%s", rid->to_string().c_str(), rc, strrc(rc));
mem_pool_item_->free(key); mem_pool_item_->free(key);
return rc; return rc;
} }
rc = insert_entry_into_leaf_node(page_handle, key, rid); rc = insert_entry_into_leaf_node(frame, key, rid);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_TRACE("Failed to insert into leaf of index %d, rid:%s", file_id_, rid->to_string().c_str()); LOG_TRACE("Failed to insert into leaf of index, rid:%s", rid->to_string().c_str());
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
mem_pool_item_->free(key); mem_pool_item_->free(key);
// disk_buffer_pool_->check_all_pages_unpinned(file_id_); // disk_buffer_pool_->check_all_pages_unpinned(file_id_);
return rc; return rc;
...@@ -1451,14 +1445,6 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid) ...@@ -1451,14 +1445,6 @@ RC BplusTreeHandler::insert_entry(const char *user_key, const RID *rid)
RC BplusTreeHandler::get_entry(const char *user_key, std::list<RID> &rids) RC BplusTreeHandler::get_entry(const char *user_key, std::list<RID> &rids)
{ {
if (file_id_ < 0) {
LOG_WARN("Index isn't ready!");
return RC::RECORD_CLOSED;
}
LOG_INFO("before get entry");
disk_buffer_pool_->check_all_pages_unpinned(file_id_);
BplusTreeScanner scanner(*this); BplusTreeScanner scanner(*this);
RC rc = scanner.open(user_key, true/*left_inclusive*/, user_key, true/*right_inclusive*/); RC rc = scanner.open(user_key, true/*left_inclusive*/, user_key, true/*right_inclusive*/);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
...@@ -1477,17 +1463,15 @@ RC BplusTreeHandler::get_entry(const char *user_key, std::list<RID> &rids) ...@@ -1477,17 +1463,15 @@ RC BplusTreeHandler::get_entry(const char *user_key, std::list<RID> &rids)
} else { } else {
rc = RC::SUCCESS; rc = RC::SUCCESS;
} }
LOG_INFO("after get entry");
disk_buffer_pool_->check_all_pages_unpinned(file_id_);
return rc; return rc;
} }
RC BplusTreeHandler::adjust_root(BPPageHandle &root_page_handle) RC BplusTreeHandler::adjust_root(Frame *root_frame)
{ {
IndexNodeHandler root_node(file_header_, root_page_handle); IndexNodeHandler root_node(file_header_, root_frame);
if (root_node.is_leaf() && root_node.size() > 0) { if (root_node.is_leaf() && root_node.size() > 0) {
root_page_handle.mark_dirty(); root_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&root_page_handle); disk_buffer_pool_->unpin_page(root_frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -1496,36 +1480,36 @@ RC BplusTreeHandler::adjust_root(BPPageHandle &root_page_handle) ...@@ -1496,36 +1480,36 @@ RC BplusTreeHandler::adjust_root(BPPageHandle &root_page_handle)
file_header_.root_page = BP_INVALID_PAGE_NUM; file_header_.root_page = BP_INVALID_PAGE_NUM;
} else { } else {
// this is an internal node and has only one child node // this is an internal node and has only one child node
InternalIndexNodeHandler internal_node(file_header_, root_page_handle); InternalIndexNodeHandler internal_node(file_header_, root_frame);
const PageNum child_page_num = internal_node.value_at(0); const PageNum child_page_num = internal_node.value_at(0);
BPPageHandle child_page_handle; Frame * child_frame;
RC rc = disk_buffer_pool_->get_this_page(file_id_, child_page_num, &child_page_handle); RC rc = disk_buffer_pool_->get_this_page(child_page_num, &child_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch child page. page num=%d, rc=%d:%s", child_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch child page. page num=%d, rc=%d:%s", child_page_num, rc, strrc(rc));
return rc; return rc;
} }
IndexNodeHandler child_node(file_header_, child_page_handle); IndexNodeHandler child_node(file_header_, child_frame);
child_node.set_parent_page_num(BP_INVALID_PAGE_NUM); child_node.set_parent_page_num(BP_INVALID_PAGE_NUM);
disk_buffer_pool_->unpin_page(&child_page_handle); disk_buffer_pool_->unpin_page(child_frame);
file_header_.root_page = child_page_num; file_header_.root_page = child_page_num;
} }
update_root_page_num(); update_root_page_num();
PageNum old_root_page_num = root_page_handle.page_num(); PageNum old_root_page_num = root_frame->page_num();
disk_buffer_pool_->unpin_page(&root_page_handle); disk_buffer_pool_->unpin_page(root_frame);
disk_buffer_pool_->dispose_page(file_id_, old_root_page_num); disk_buffer_pool_->dispose_page(old_root_page_num);
return RC::SUCCESS; return RC::SUCCESS;
} }
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC BplusTreeHandler::coalesce_or_redistribute(BPPageHandle &page_handle) RC BplusTreeHandler::coalesce_or_redistribute(Frame *frame)
{ {
IndexNodeHandlerType index_node(file_header_, page_handle); IndexNodeHandlerType index_node(file_header_, frame);
if (index_node.size() >= index_node.min_size()) { if (index_node.size() >= index_node.min_size()) {
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -1533,27 +1517,27 @@ RC BplusTreeHandler::coalesce_or_redistribute(BPPageHandle &page_handle) ...@@ -1533,27 +1517,27 @@ RC BplusTreeHandler::coalesce_or_redistribute(BPPageHandle &page_handle)
if (BP_INVALID_PAGE_NUM == parent_page_num) { if (BP_INVALID_PAGE_NUM == parent_page_num) {
// this is the root page // this is the root page
if (index_node.size() > 1) { if (index_node.size() > 1) {
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
} else { } else {
// adjust the root node // adjust the root node
adjust_root(page_handle); adjust_root(frame);
} }
return RC::SUCCESS; return RC::SUCCESS;
} }
BPPageHandle parent_page_handle; Frame * parent_frame;
RC rc = disk_buffer_pool_->get_this_page(file_id_, parent_page_num, &parent_page_handle); RC rc = disk_buffer_pool_->get_this_page(parent_page_num, &parent_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch parent page. page id=%d, rc=%d:%s", parent_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch parent page. page id=%d, rc=%d:%s", parent_page_num, rc, strrc(rc));
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return rc; return rc;
} }
InternalIndexNodeHandler parent_index_node(file_header_, parent_page_handle); InternalIndexNodeHandler parent_index_node(file_header_, parent_frame);
int index = parent_index_node.lookup(key_comparator_, index_node.key_at(index_node.size() - 1)); int index = parent_index_node.lookup(key_comparator_, index_node.key_at(index_node.size() - 1));
if (parent_index_node.value_at(index) != page_handle.page_num()) { if (parent_index_node.value_at(index) != frame->page_num()) {
LOG_ERROR("lookup return an invalid value. index=%d, this page num=%d, but got %d", LOG_ERROR("lookup return an invalid value. index=%d, this page num=%d, but got %d",
index, page_handle.page_num(), parent_index_node.value_at(index)); index, frame->page_num(), parent_index_node.value_at(index));
} }
PageNum neighbor_page_num; PageNum neighbor_page_num;
if (index == 0) { if (index == 0) {
...@@ -1562,53 +1546,52 @@ RC BplusTreeHandler::coalesce_or_redistribute(BPPageHandle &page_handle) ...@@ -1562,53 +1546,52 @@ RC BplusTreeHandler::coalesce_or_redistribute(BPPageHandle &page_handle)
neighbor_page_num = parent_index_node.value_at(index - 1); neighbor_page_num = parent_index_node.value_at(index - 1);
} }
BPPageHandle neighbor_page_handle; Frame * neighbor_frame;
rc = disk_buffer_pool_->get_this_page(file_id_, neighbor_page_num, &neighbor_page_handle); rc = disk_buffer_pool_->get_this_page(neighbor_page_num, &neighbor_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch neighbor page. page id=%d, rc=%d:%s", neighbor_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch neighbor page. page id=%d, rc=%d:%s", neighbor_page_num, rc, strrc(rc));
// TODO do more thing to release resource // TODO do more thing to release resource
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&parent_page_handle); disk_buffer_pool_->unpin_page(parent_frame);
return rc; return rc;
} }
IndexNodeHandlerType neighbor_node(file_header_, neighbor_page_handle); IndexNodeHandlerType neighbor_node(file_header_, neighbor_frame);
if (index_node.size() + neighbor_node.size() > index_node.max_size()) { if (index_node.size() + neighbor_node.size() > index_node.max_size()) {
rc = redistribute<IndexNodeHandlerType>(neighbor_page_handle, page_handle, parent_page_handle, index); rc = redistribute<IndexNodeHandlerType>(neighbor_frame, frame, parent_frame, index);
} else { } else {
rc = coalesce<IndexNodeHandlerType>(neighbor_page_handle, page_handle, parent_page_handle, index); rc = coalesce<IndexNodeHandlerType>(neighbor_frame, frame, parent_frame, index);
} }
return rc; return rc;
} }
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC BplusTreeHandler::coalesce(BPPageHandle &neighbor_page_handle, BPPageHandle &page_handle, RC BplusTreeHandler::coalesce(Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index)
BPPageHandle &parent_page_handle, int index)
{ {
IndexNodeHandlerType neighbor_node(file_header_, neighbor_page_handle); IndexNodeHandlerType neighbor_node(file_header_, neighbor_frame);
IndexNodeHandlerType node(file_header_, page_handle); IndexNodeHandlerType node(file_header_, frame);
InternalIndexNodeHandler parent_node(file_header_, parent_page_handle); InternalIndexNodeHandler parent_node(file_header_, parent_frame);
BPPageHandle *left_page_handle = nullptr; Frame *left_frame = nullptr;
BPPageHandle *right_page_handle = nullptr; Frame *right_frame = nullptr;
if (index == 0) { if (index == 0) {
// neighbor node is at right // neighbor node is at right
left_page_handle = &page_handle; left_frame = frame;
right_page_handle = &neighbor_page_handle; right_frame = neighbor_frame;
index++; index++;
} else { } else {
left_page_handle = &neighbor_page_handle; left_frame = neighbor_frame;
right_page_handle = &page_handle; right_frame = frame;
// neighbor is at left // neighbor is at left
} }
IndexNodeHandlerType left_node(file_header_, *left_page_handle); IndexNodeHandlerType left_node(file_header_, left_frame);
IndexNodeHandlerType right_node(file_header_, *right_page_handle); IndexNodeHandlerType right_node(file_header_, right_frame);
parent_node.remove(index); parent_node.remove(index);
// parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
RC rc = right_node.move_to(left_node, disk_buffer_pool_, file_id_); RC rc = right_node.move_to(left_node, disk_buffer_pool_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to move right node to left. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to move right node to left. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
...@@ -1616,101 +1599,95 @@ RC BplusTreeHandler::coalesce(BPPageHandle &neighbor_page_handle, BPPageHandle & ...@@ -1616,101 +1599,95 @@ RC BplusTreeHandler::coalesce(BPPageHandle &neighbor_page_handle, BPPageHandle &
// left_node.validate(key_comparator_); // left_node.validate(key_comparator_);
if (left_node.is_leaf()) { if (left_node.is_leaf()) {
LeafIndexNodeHandler left_leaf_node(file_header_, *left_page_handle); LeafIndexNodeHandler left_leaf_node(file_header_, left_frame);
LeafIndexNodeHandler right_leaf_node(file_header_, *right_page_handle); LeafIndexNodeHandler right_leaf_node(file_header_, right_frame);
left_leaf_node.set_next_page(right_leaf_node.next_page()); left_leaf_node.set_next_page(right_leaf_node.next_page());
PageNum next_right_page_num = right_leaf_node.next_page(); PageNum next_right_page_num = right_leaf_node.next_page();
if (next_right_page_num != BP_INVALID_PAGE_NUM) { if (next_right_page_num != BP_INVALID_PAGE_NUM) {
BPPageHandle next_right_page_handle; Frame *next_right_frame;
rc = disk_buffer_pool_->get_this_page(file_id_, next_right_page_num, &next_right_page_handle); rc = disk_buffer_pool_->get_this_page(next_right_page_num, &next_right_frame);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next right page. page number:%d. rc=%d:%s", next_right_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next right page. page number:%d. rc=%d:%s", next_right_page_num, rc, strrc(rc));
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
disk_buffer_pool_->unpin_page(&neighbor_page_handle); disk_buffer_pool_->unpin_page(neighbor_frame);
disk_buffer_pool_->unpin_page(&parent_page_handle); disk_buffer_pool_->unpin_page(parent_frame);
return rc; return rc;
} }
LeafIndexNodeHandler next_right_node(file_header_, next_right_page_handle); LeafIndexNodeHandler next_right_node(file_header_, next_right_frame);
next_right_node.set_prev_page(left_node.page_num()); next_right_node.set_prev_page(left_node.page_num());
disk_buffer_pool_->unpin_page(&next_right_page_handle); disk_buffer_pool_->unpin_page(next_right_frame);
} }
} }
PageNum right_page_num = right_page_handle->page_num(); PageNum right_page_num = right_frame->page_num();
disk_buffer_pool_->unpin_page(left_page_handle); disk_buffer_pool_->unpin_page(left_frame);
disk_buffer_pool_->unpin_page(right_page_handle); disk_buffer_pool_->unpin_page(right_frame);
disk_buffer_pool_->dispose_page(file_id_, right_page_num); disk_buffer_pool_->dispose_page(right_page_num);
return coalesce_or_redistribute<InternalIndexNodeHandler>(parent_page_handle); return coalesce_or_redistribute<InternalIndexNodeHandler>(parent_frame);
} }
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC BplusTreeHandler::redistribute(BPPageHandle &neighbor_page_handle, BPPageHandle &page_handle, RC BplusTreeHandler::redistribute(Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index)
BPPageHandle &parent_page_handle, int index)
{ {
InternalIndexNodeHandler parent_node(file_header_, parent_page_handle); InternalIndexNodeHandler parent_node(file_header_, parent_frame);
IndexNodeHandlerType neighbor_node(file_header_, neighbor_page_handle); IndexNodeHandlerType neighbor_node(file_header_, neighbor_frame);
IndexNodeHandlerType node(file_header_, page_handle); IndexNodeHandlerType node(file_header_, frame);
if (neighbor_node.size() < node.size()) { if (neighbor_node.size() < node.size()) {
LOG_ERROR("got invalid nodes. neighbor node size %d, this node size %d", LOG_ERROR("got invalid nodes. neighbor node size %d, this node size %d",
neighbor_node.size(), node.size()); neighbor_node.size(), node.size());
} }
if (index == 0) { if (index == 0) {
// the neighbor is at right // the neighbor is at right
neighbor_node.move_first_to_end(node, disk_buffer_pool_, file_id_); neighbor_node.move_first_to_end(node, disk_buffer_pool_);
// neighbor_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // neighbor_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
// node.validate(key_comparator_, disk_buffer_pool_, file_id_); // node.validate(key_comparator_, disk_buffer_pool_, file_id_);
parent_node.set_key_at(index + 1, neighbor_node.key_at(0)); parent_node.set_key_at(index + 1, neighbor_node.key_at(0));
// parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
} else { } else {
// the neighbor is at left // the neighbor is at left
neighbor_node.move_last_to_front(node, disk_buffer_pool_, file_id_); neighbor_node.move_last_to_front(node, disk_buffer_pool_);
// neighbor_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // neighbor_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
// node.validate(key_comparator_, disk_buffer_pool_, file_id_); // node.validate(key_comparator_, disk_buffer_pool_, file_id_);
parent_node.set_key_at(index, node.key_at(0)); parent_node.set_key_at(index, node.key_at(0));
// parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // parent_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
} }
neighbor_page_handle.mark_dirty(); neighbor_frame->mark_dirty();
page_handle.mark_dirty(); frame->mark_dirty();
parent_page_handle.mark_dirty(); parent_frame->mark_dirty();
disk_buffer_pool_->unpin_page(&parent_page_handle); disk_buffer_pool_->unpin_page(parent_frame);
disk_buffer_pool_->unpin_page(&neighbor_page_handle); disk_buffer_pool_->unpin_page(neighbor_frame);
disk_buffer_pool_->unpin_page(&page_handle); disk_buffer_pool_->unpin_page(frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
RC BplusTreeHandler::delete_entry_internal(BPPageHandle &leaf_page_handle, const char *key) RC BplusTreeHandler::delete_entry_internal(Frame *leaf_frame, const char *key)
{ {
LeafIndexNodeHandler leaf_index_node(file_header_, leaf_page_handle); LeafIndexNodeHandler leaf_index_node(file_header_, leaf_frame);
const int remove_count = leaf_index_node.remove(key, key_comparator_); const int remove_count = leaf_index_node.remove(key, key_comparator_);
if (remove_count == 0) { if (remove_count == 0) {
LOG_TRACE("no data to remove"); LOG_TRACE("no data to remove");
disk_buffer_pool_->unpin_page(&leaf_page_handle); disk_buffer_pool_->unpin_page(leaf_frame);
return RC::RECORD_RECORD_NOT_EXIST; return RC::RECORD_RECORD_NOT_EXIST;
} }
// leaf_index_node.validate(key_comparator_, disk_buffer_pool_, file_id_); // leaf_index_node.validate(key_comparator_, disk_buffer_pool_, file_id_);
leaf_page_handle.mark_dirty(); leaf_frame->mark_dirty();
if (leaf_index_node.size() >= leaf_index_node.min_size()) { if (leaf_index_node.size() >= leaf_index_node.min_size()) {
disk_buffer_pool_->unpin_page(&leaf_page_handle); disk_buffer_pool_->unpin_page(leaf_frame);
return RC::SUCCESS; return RC::SUCCESS;
} }
return coalesce_or_redistribute<LeafIndexNodeHandler>(leaf_page_handle); return coalesce_or_redistribute<LeafIndexNodeHandler>(leaf_frame);
} }
RC BplusTreeHandler::delete_entry(const char *user_key, const RID *rid) RC BplusTreeHandler::delete_entry(const char *user_key, const RID *rid)
{ {
if (file_id_ < 0) {
LOG_WARN("Failed to delete index entry, due to index is't ready");
return RC::RECORD_CLOSED;
}
char *key = (char *)mem_pool_item_->alloc(); char *key = (char *)mem_pool_item_->alloc();
if (nullptr == key) { if (nullptr == key) {
LOG_WARN("Failed to alloc memory for key. size=%d", file_header_.key_length); LOG_WARN("Failed to alloc memory for key. size=%d", file_header_.key_length);
...@@ -1719,24 +1696,20 @@ RC BplusTreeHandler::delete_entry(const char *user_key, const RID *rid) ...@@ -1719,24 +1696,20 @@ RC BplusTreeHandler::delete_entry(const char *user_key, const RID *rid)
memcpy(key, user_key, file_header_.attr_length); memcpy(key, user_key, file_header_.attr_length);
memcpy(key + file_header_.attr_length, rid, sizeof(*rid)); memcpy(key + file_header_.attr_length, rid, sizeof(*rid));
LOG_INFO("before delete"); Frame *leaf_frame;
disk_buffer_pool_->check_all_pages_unpinned(file_id_); RC rc = find_leaf(key, leaf_frame);
BPPageHandle leaf_page_handle;
RC rc = find_leaf(key, leaf_page_handle);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to find leaf page. rc =%d:%s", rc, strrc(rc)); LOG_WARN("failed to find leaf page. rc =%d:%s", rc, strrc(rc));
mem_pool_item_->free(key); mem_pool_item_->free(key);
return rc; return rc;
} }
rc = delete_entry_internal(leaf_page_handle, key); rc = delete_entry_internal(leaf_frame, key);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("Failed to delete index %d", file_id_); LOG_WARN("Failed to delete index");
mem_pool_item_->free(key); mem_pool_item_->free(key);
return rc; return rc;
} }
mem_pool_item_->free(key); mem_pool_item_->free(key);
LOG_INFO("after delete");
disk_buffer_pool_->check_all_pages_unpinned(file_id_);
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -1771,7 +1744,7 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1771,7 +1744,7 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
} }
if (nullptr == left_user_key) { if (nullptr == left_user_key) {
rc = tree_handler_.left_most_page(left_page_handle_); rc = tree_handler_.left_most_page(left_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to find left most page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to find left most page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
...@@ -1785,14 +1758,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1785,14 +1758,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
} else { } else {
left_key = tree_handler_.make_key(left_user_key, *RID::max()); left_key = tree_handler_.make_key(left_user_key, *RID::max());
} }
rc = tree_handler_.find_leaf(left_key, left_page_handle_); rc = tree_handler_.find_leaf(left_key, left_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to find left page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to find left page. rc=%d:%s", rc, strrc(rc));
tree_handler_.free_key(left_key); tree_handler_.free_key(left_key);
return rc; return rc;
} }
LeafIndexNodeHandler left_node(tree_handler_.file_header_, left_page_handle_); LeafIndexNodeHandler left_node(tree_handler_.file_header_, left_frame_);
int left_index = left_node.lookup(tree_handler_.key_comparator_, left_key); int left_index = left_node.lookup(tree_handler_.key_comparator_, left_key);
tree_handler_.free_key(left_key); tree_handler_.free_key(left_key);
// lookup 返回的是适合插入的位置,还需要判断一下是否在合适的边界范围内 // lookup 返回的是适合插入的位置,还需要判断一下是否在合适的边界范围内
...@@ -1802,8 +1775,8 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1802,8 +1775,8 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
return RC::SUCCESS; return RC::SUCCESS;
} }
tree_handler_.disk_buffer_pool_->unpin_page(&left_page_handle_); tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
rc = tree_handler_.disk_buffer_pool_->get_this_page(tree_handler_.file_id_, next_page_num, &left_page_handle_); rc = tree_handler_.disk_buffer_pool_->get_this_page(next_page_num, &left_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", next_page_num, rc, strrc(rc));
return rc; return rc;
...@@ -1816,13 +1789,13 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1816,13 +1789,13 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
// 没有指定右边界范围,那么就返回右边界最大值 // 没有指定右边界范围,那么就返回右边界最大值
if (nullptr == right_user_key) { if (nullptr == right_user_key) {
rc = tree_handler_.right_most_page(right_page_handle_); rc = tree_handler_.right_most_page(right_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch right most page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to fetch right most page. rc=%d:%s", rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler node(tree_handler_.file_header_, right_page_handle_); LeafIndexNodeHandler node(tree_handler_.file_header_, right_frame_);
end_index_ = node.size() - 1; end_index_ = node.size() - 1;
} else { } else {
...@@ -1833,14 +1806,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1833,14 +1806,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
right_key = tree_handler_.make_key(right_user_key, *RID::min()); right_key = tree_handler_.make_key(right_user_key, *RID::min());
} }
rc = tree_handler_.find_leaf(right_key, right_page_handle_); rc = tree_handler_.find_leaf(right_key, right_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to find left page. rc=%d:%s", rc, strrc(rc)); LOG_WARN("failed to find left page. rc=%d:%s", rc, strrc(rc));
tree_handler_.free_key(right_key); tree_handler_.free_key(right_key);
return rc; return rc;
} }
LeafIndexNodeHandler right_node(tree_handler_.file_header_, right_page_handle_); LeafIndexNodeHandler right_node(tree_handler_.file_header_, right_frame_);
int right_index = right_node.lookup(tree_handler_.key_comparator_, right_key); int right_index = right_node.lookup(tree_handler_.key_comparator_, right_key);
tree_handler_.free_key(right_key); tree_handler_.free_key(right_key);
// lookup 返回的是适合插入的位置,需要根据实际情况做调整 // lookup 返回的是适合插入的位置,需要根据实际情况做调整
...@@ -1856,14 +1829,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1856,14 +1829,14 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
return RC::SUCCESS; return RC::SUCCESS;
} }
tree_handler_.disk_buffer_pool_->unpin_page(&right_page_handle_); tree_handler_.disk_buffer_pool_->unpin_page(right_frame_);
rc = tree_handler_.disk_buffer_pool_->get_this_page(tree_handler_.file_id_, prev_page_num, &right_page_handle_); rc = tree_handler_.disk_buffer_pool_->get_this_page(prev_page_num, &right_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch prev page num. page num=%d, rc=%d:%s", prev_page_num, rc, strrc(rc)); LOG_WARN("failed to fetch prev page num. page num=%d, rc=%d:%s", prev_page_num, rc, strrc(rc));
return rc; return rc;
} }
LeafIndexNodeHandler tmp_node(tree_handler_.file_header_, right_page_handle_); LeafIndexNodeHandler tmp_node(tree_handler_.file_header_, right_frame_);
right_index = tmp_node.size() - 1; right_index = tmp_node.size() - 1;
} }
end_index_ = right_index; end_index_ = right_index;
...@@ -1872,12 +1845,12 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive, ...@@ -1872,12 +1845,12 @@ RC BplusTreeScanner::open(const char *left_user_key, bool left_inclusive,
// 判断是否左边界比右边界要靠后 // 判断是否左边界比右边界要靠后
// 两个边界最多会多一页 // 两个边界最多会多一页
// 查找不存在的元素,或者不存在的范围数据时,可能会存在这个问题 // 查找不存在的元素,或者不存在的范围数据时,可能会存在这个问题
if (left_page_handle_.page_num() == right_page_handle_.page_num() && if (left_frame_->page_num() == right_frame_->page_num() &&
iter_index_ > end_index_) { iter_index_ > end_index_) {
end_index_ = -1; end_index_ = -1;
} else { } else {
LeafIndexNodeHandler left_node(tree_handler_.file_header_, left_page_handle_); LeafIndexNodeHandler left_node(tree_handler_.file_header_, left_frame_);
LeafIndexNodeHandler right_node(tree_handler_.file_header_, right_page_handle_); LeafIndexNodeHandler right_node(tree_handler_.file_header_, right_frame_);
if (left_node.prev_page() == right_node.page_num()) { if (left_node.prev_page() == right_node.page_num()) {
end_index_ = -1; end_index_ = -1;
} }
...@@ -1891,10 +1864,10 @@ RC BplusTreeScanner::next_entry(RID *rid) ...@@ -1891,10 +1864,10 @@ RC BplusTreeScanner::next_entry(RID *rid)
return RC::RECORD_EOF; return RC::RECORD_EOF;
} }
LeafIndexNodeHandler node(tree_handler_.file_header_, left_page_handle_); LeafIndexNodeHandler node(tree_handler_.file_header_, left_frame_);
memcpy(rid, node.value_at(iter_index_), sizeof(*rid)); memcpy(rid, node.value_at(iter_index_), sizeof(*rid));
if (left_page_handle_.page_num() == right_page_handle_.page_num() && if (left_frame_->page_num() == right_frame_->page_num() &&
iter_index_ == end_index_) { iter_index_ == end_index_) {
end_index_ = -1; end_index_ = -1;
return RC::SUCCESS; return RC::SUCCESS;
...@@ -1906,14 +1879,14 @@ RC BplusTreeScanner::next_entry(RID *rid) ...@@ -1906,14 +1879,14 @@ RC BplusTreeScanner::next_entry(RID *rid)
} }
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
if (left_page_handle_.page_num() != right_page_handle_.page_num()) { if (left_frame_->page_num() != right_frame_->page_num()) {
PageNum page_num = node.next_page(); PageNum page_num = node.next_page();
tree_handler_.disk_buffer_pool_->unpin_page(&left_page_handle_); tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
if (page_num == BP_INVALID_PAGE_NUM) { if (page_num == BP_INVALID_PAGE_NUM) {
LOG_WARN("got invalid next page. page num=%d", page_num); LOG_WARN("got invalid next page. page num=%d", page_num);
rc = RC::INTERNAL; rc = RC::INTERNAL;
} else { } else {
rc = tree_handler_.disk_buffer_pool_->get_this_page(tree_handler_.file_id_, page_num, &left_page_handle_); rc = tree_handler_.disk_buffer_pool_->get_this_page(page_num, &left_frame_);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", page_num, rc, strrc(rc)); LOG_WARN("failed to fetch next page. page num=%d, rc=%d:%s", page_num, rc, strrc(rc));
return rc; return rc;
...@@ -1923,7 +1896,7 @@ RC BplusTreeScanner::next_entry(RID *rid) ...@@ -1923,7 +1896,7 @@ RC BplusTreeScanner::next_entry(RID *rid)
} }
} else if (end_index_ != -1) { } else if (end_index_ != -1) {
LOG_WARN("should have more pages but not. left page=%d, right page=%d", LOG_WARN("should have more pages but not. left page=%d, right page=%d",
left_page_handle_.page_num(), right_page_handle_.page_num()); left_frame_->page_num(), right_frame_->page_num());
rc = RC::INTERNAL; rc = RC::INTERNAL;
} }
return rc; return rc;
...@@ -1931,11 +1904,11 @@ RC BplusTreeScanner::next_entry(RID *rid) ...@@ -1931,11 +1904,11 @@ RC BplusTreeScanner::next_entry(RID *rid)
RC BplusTreeScanner::close() RC BplusTreeScanner::close()
{ {
if (left_page_handle_.open) { if (left_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(&left_page_handle_); tree_handler_.disk_buffer_pool_->unpin_page(left_frame_);
} }
if (right_page_handle_.open) { if (right_frame_ != nullptr) {
tree_handler_.disk_buffer_pool_->unpin_page(&right_page_handle_); tree_handler_.disk_buffer_pool_->unpin_page(right_frame_);
} }
end_index_ = -1; end_index_ = -1;
inited_ = false; inited_ = false;
......
...@@ -19,6 +19,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -19,6 +19,7 @@ See the Mulan PSL v2 for more details. */
#include <string.h> #include <string.h>
#include <sstream> #include <sstream>
#include <functional>
#include "storage/common/record_manager.h" #include "storage/common/record_manager.h"
#include "storage/default/disk_buffer_pool.h" #include "storage/default/disk_buffer_pool.h"
...@@ -244,17 +245,17 @@ struct InternalIndexNode : public IndexNode { ...@@ -244,17 +245,17 @@ struct InternalIndexNode : public IndexNode {
class IndexNodeHandler { class IndexNodeHandler {
public: public:
IndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle); IndexNodeHandler(const IndexFileHeader &header, Frame *frame);
void init_empty(bool leaf); void init_empty(bool leaf);
bool is_leaf() const; bool is_leaf() const;
int key_size() const; int key_size() const;
int value_size() const; int value_size() const;
int item_size() const; int item_size() const;
void increase_size(int n); void increase_size(int n);
int size() const; int size() const;
void set_parent_page_num(PageNum page_num); void set_parent_page_num(PageNum page_num);
PageNum parent_page_num() const; PageNum parent_page_num() const;
...@@ -272,7 +273,7 @@ protected: ...@@ -272,7 +273,7 @@ protected:
class LeafIndexNodeHandler : public IndexNodeHandler { class LeafIndexNodeHandler : public IndexNodeHandler {
public: public:
LeafIndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle); LeafIndexNodeHandler(const IndexFileHeader &header, Frame *frame);
void init_empty(); void init_empty();
void set_next_page(PageNum page_num); void set_next_page(PageNum page_num);
...@@ -293,18 +294,18 @@ public: ...@@ -293,18 +294,18 @@ public:
void insert(int index, const char *key, const char *value); void insert(int index, const char *key, const char *value);
void remove(int index); void remove(int index);
int remove(const char *key, const KeyComparator &comparator); int remove(const char *key, const KeyComparator &comparator);
RC move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp);
RC move_first_to_end(LeafIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id); RC move_first_to_end(LeafIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool);
RC move_last_to_front(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_last_to_front(LeafIndexNodeHandler &other, DiskBufferPool *bp);
/** /**
* move all items to left page * move all items to left page
*/ */
RC move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_to(LeafIndexNodeHandler &other, DiskBufferPool *bp);
int max_size() const; int max_size() const;
int min_size() const; int min_size() const;
bool validate(const KeyComparator &comparator, DiskBufferPool *bp, int file_id) const; bool validate(const KeyComparator &comparator, DiskBufferPool *bp) const;
friend std::string to_string(const LeafIndexNodeHandler &handler, const KeyPrinter &printer); friend std::string to_string(const LeafIndexNodeHandler &handler, const KeyPrinter &printer);
private: private:
...@@ -321,20 +322,20 @@ private: ...@@ -321,20 +322,20 @@ private:
class InternalIndexNodeHandler : public IndexNodeHandler { class InternalIndexNodeHandler : public IndexNodeHandler {
public: public:
InternalIndexNodeHandler(const IndexFileHeader &header, BPPageHandle &page_handle); InternalIndexNodeHandler(const IndexFileHeader &header, Frame *frame);
void init_empty(); void init_empty();
void create_new_root(PageNum first_page_num, const char *key, PageNum page_num); void create_new_root(PageNum first_page_num, const char *key, PageNum page_num);
void insert(const char *key, PageNum page_num, const KeyComparator &comparator); void insert(const char *key, PageNum page_num, const KeyComparator &comparator);
RC move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_half_to(LeafIndexNodeHandler &other, DiskBufferPool *bp);
char *key_at(int index); char *key_at(int index);
PageNum value_at(int index); PageNum value_at(int index);
/** /**
* 返回指定子节点在当前节点中的索引 * 返回指定子节点在当前节点中的索引
*/ */
int value_index(PageNum page_num); int value_index(PageNum page_num);
void set_key_at(int index, const char *key); void set_key_at(int index, const char *key);
void remove(int index); void remove(int index);
...@@ -349,18 +350,18 @@ public: ...@@ -349,18 +350,18 @@ public:
int max_size() const; int max_size() const;
int min_size() const; int min_size() const;
RC move_to(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id); RC move_to(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool);
RC move_first_to_end(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool, int file_id); RC move_first_to_end(InternalIndexNodeHandler &other, DiskBufferPool *disk_buffer_pool);
RC move_last_to_front(InternalIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_last_to_front(InternalIndexNodeHandler &other, DiskBufferPool *bp);
RC move_half_to(InternalIndexNodeHandler &other, DiskBufferPool *bp, int file_id); RC move_half_to(InternalIndexNodeHandler &other, DiskBufferPool *bp);
bool validate(const KeyComparator &comparator, DiskBufferPool *bp, int file_id) const; bool validate(const KeyComparator &comparator, DiskBufferPool *bp) const;
friend std::string to_string(const InternalIndexNodeHandler &handler, const KeyPrinter &printer); friend std::string to_string(const InternalIndexNodeHandler &handler, const KeyPrinter &printer);
private: private:
RC copy_from(const char *items, int num, DiskBufferPool *disk_buffer_pool, int file_id); RC copy_from(const char *items, int num, DiskBufferPool *disk_buffer_pool);
RC append(const char *item, DiskBufferPool *bp, int file_id); RC append(const char *item, DiskBufferPool *bp);
RC preappend(const char *item, DiskBufferPool *bp, int file_id); RC preappend(const char *item, DiskBufferPool *bp);
private: private:
char *__item_at(int index) const; char *__item_at(int index) const;
...@@ -418,11 +419,6 @@ public: ...@@ -418,11 +419,6 @@ public:
RC sync(); RC sync();
const int get_file_id()
{
return file_id_;
}
/** /**
* Check whether current B+ tree is invalid or not. * Check whether current B+ tree is invalid or not.
* return true means current tree is valid, return false means current tree is invalid. * return true means current tree is valid, return false means current tree is invalid.
...@@ -435,52 +431,48 @@ public: ...@@ -435,52 +431,48 @@ public:
RC print_leafs(); RC print_leafs();
private: private:
RC print_leaf(BPPageHandle &page_handle); RC print_leaf(Frame *frame);
RC print_internal_node_recursive(BPPageHandle &page_handle); RC print_internal_node_recursive(Frame *frame);
bool validate_node(IndexNode *node); bool validate_node(IndexNode *node);
bool validate_leaf_link(); bool validate_leaf_link();
bool validate_node_recursive(BPPageHandle &page_handle); bool validate_node_recursive(Frame *frame);
protected: protected:
RC find_leaf(const char *key, BPPageHandle &page_handle); RC find_leaf(const char *key, Frame *&frame);
RC left_most_page(BPPageHandle &page_handle); RC left_most_page(Frame *&frame);
RC right_most_page(BPPageHandle &page_handle); RC right_most_page(Frame *&frame);
RC find_leaf_internal(const std::function<PageNum(InternalIndexNodeHandler &)> &child_page_getter, RC find_leaf_internal(const std::function<PageNum(InternalIndexNodeHandler &)> &child_page_getter,
BPPageHandle &page_handle); Frame *&frame);
RC insert_into_parent( RC insert_into_parent(
PageNum parent_page, BPPageHandle &left_page_handle, const char *pkey, BPPageHandle &right_page_handle); PageNum parent_page, Frame *left_frame, const char *pkey, Frame &right_frame);
RC split_leaf(BPPageHandle &leaf_page_handle);
RC delete_entry_internal(BPPageHandle &leaf_page_handle, const char *key); RC delete_entry_internal(Frame *leaf_frame, const char *key);
RC insert_into_new_root(BPPageHandle &left_page_handle, const char *pkey, BPPageHandle &right_page_handle); RC insert_into_new_root(Frame *left_frame, const char *pkey, Frame &right_frame);
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC split(BPPageHandle &page_handle, BPPageHandle &new_page_handle); RC split(Frame *frame, Frame *&new_frame);
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC coalesce_or_redistribute(BPPageHandle &page_handle); RC coalesce_or_redistribute(Frame *frame);
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC coalesce(BPPageHandle &neighbor_page_handle, BPPageHandle &page_handle, RC coalesce(Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index);
BPPageHandle &parent_page_handle, int index);
template <typename IndexNodeHandlerType> template <typename IndexNodeHandlerType>
RC redistribute(BPPageHandle &neighbor_page_handle, BPPageHandle &page_handle, RC redistribute(Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index);
BPPageHandle &parent_page_handle, int index);
RC insert_entry_into_parent(BPPageHandle &page_handle, BPPageHandle &new_page_handle, const char *key); RC insert_entry_into_parent(Frame *frame, Frame *new_frame, const char *key);
RC insert_entry_into_leaf_node(BPPageHandle &page_handle, const char *pkey, const RID *rid); RC insert_entry_into_leaf_node(Frame *frame, const char *pkey, const RID *rid);
RC update_root_page_num(); RC update_root_page_num();
RC create_new_tree(const char *key, const RID *rid); RC create_new_tree(const char *key, const RID *rid);
RC adjust_root(BPPageHandle &root_page_handle); RC adjust_root(Frame *root_frame);
private: private:
char *make_key(const char *user_key, const RID &rid); char *make_key(const char *user_key, const RID &rid);
void free_key(char *key); void free_key(char *key);
protected: protected:
DiskBufferPool *disk_buffer_pool_ = nullptr; DiskBufferPool *disk_buffer_pool_ = nullptr;
int file_id_ = -1;
bool header_dirty_ = false; bool header_dirty_ = false;
IndexFileHeader file_header_; IndexFileHeader file_header_;
...@@ -519,10 +511,10 @@ private: ...@@ -519,10 +511,10 @@ private:
/// 使用左右叶子节点和位置来表示扫描的起始位置和终止位置 /// 使用左右叶子节点和位置来表示扫描的起始位置和终止位置
/// 起始位置和终止位置都是有效的数据 /// 起始位置和终止位置都是有效的数据
BPPageHandle left_page_handle_; Frame * left_frame_ = nullptr;
BPPageHandle right_page_handle_; Frame * right_frame_ = nullptr;
int iter_index_ = -1; int iter_index_ = -1;
int end_index_ = -1; // use -1 for end of scan int end_index_ = -1; // use -1 for end of scan
}; };
#endif //__OBSERVER_STORAGE_COMMON_INDEX_MANAGER_H_ #endif //__OBSERVER_STORAGE_COMMON_INDEX_MANAGER_H_
...@@ -79,10 +79,8 @@ RC BplusTreeIndex::open(const char *file_name, const IndexMeta &index_meta, cons ...@@ -79,10 +79,8 @@ RC BplusTreeIndex::open(const char *file_name, const IndexMeta &index_meta, cons
RC BplusTreeIndex::close() RC BplusTreeIndex::close()
{ {
if (inited_) { if (inited_) {
LOG_INFO("Begin to close index, file_id:%d, index:%s, field:%s", LOG_INFO("Begin to close index, index:%s, field:%s",
index_handler_.get_file_id(), index_meta_.name(), index_meta_.field());
index_meta_.name(),
index_meta_.field());
index_handler_.close(); index_handler_.close();
inited_ = false; inited_ = false;
} }
......
...@@ -15,68 +15,68 @@ See the Mulan PSL v2 for more details. */ ...@@ -15,68 +15,68 @@ See the Mulan PSL v2 for more details. */
#include "storage/default/disk_buffer_pool.h" #include "storage/default/disk_buffer_pool.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
void test_get(BPManager &bp_manager) void test_get(BPFrameManager &frame_manager)
{ {
Frame *frame1 = bp_manager.alloc(); Frame *frame1 = frame_manager.alloc();
ASSERT_NE(frame1, nullptr); ASSERT_NE(frame1, nullptr);
frame1->file_desc = 0; frame1->set_file_desc(0);
frame1->page.page_num = 1; frame1->set_page_num(1);
ASSERT_EQ(frame1, bp_manager.get(0, 1)); ASSERT_EQ(frame1, frame_manager.get(0, 1));
Frame *frame2 = bp_manager.alloc(); Frame *frame2 = frame_manager.alloc();
ASSERT_NE(frame2, nullptr); ASSERT_NE(frame2, nullptr);
frame2->file_desc = 0; frame2->set_file_desc(0);
frame2->page.page_num = 2; frame2->set_page_num(2);
ASSERT_EQ(frame1, bp_manager.get(0, 1)); ASSERT_EQ(frame1, frame_manager.get(0, 1));
Frame *frame3 = bp_manager.alloc(); Frame *frame3 = frame_manager.alloc();
ASSERT_NE(frame3, nullptr); ASSERT_NE(frame3, nullptr);
frame3->file_desc = 0; frame3->set_file_desc(0);
frame3->page.page_num = 3; frame3->set_page_num(3);
frame2 = bp_manager.get(0, 2); frame2 = frame_manager.get(0, 2);
ASSERT_NE(frame2, nullptr); ASSERT_NE(frame2, nullptr);
Frame *frame4 = bp_manager.alloc(); Frame *frame4 = frame_manager.alloc();
frame4->file_desc = 0; frame4->set_file_desc(0);
frame4->page.page_num = 4; frame4->set_page_num(4);
bp_manager.free(frame1); frame_manager.free(frame1);
frame1 = bp_manager.get(0, 1); frame1 = frame_manager.get(0, 1);
ASSERT_EQ(frame1, nullptr); ASSERT_EQ(frame1, nullptr);
ASSERT_EQ(frame3, bp_manager.get(0, 3)); ASSERT_EQ(frame3, frame_manager.get(0, 3));
ASSERT_EQ(frame4, bp_manager.get(0, 4)); ASSERT_EQ(frame4, frame_manager.get(0, 4));
bp_manager.free(frame2); frame_manager.free(frame2);
bp_manager.free(frame3); frame_manager.free(frame3);
bp_manager.free(frame4); frame_manager.free(frame4);
ASSERT_EQ(nullptr, bp_manager.get(0, 2)); ASSERT_EQ(nullptr, frame_manager.get(0, 2));
ASSERT_EQ(nullptr, bp_manager.get(0, 3)); ASSERT_EQ(nullptr, frame_manager.get(0, 3));
ASSERT_EQ(nullptr, bp_manager.get(0, 4)); ASSERT_EQ(nullptr, frame_manager.get(0, 4));
} }
void test_alloc(BPManager &bp_manager) void test_alloc(BPFrameManager &frame_manager)
{ {
int size = bp_manager.get_size(); int size = frame_manager.get_size();
std::list<Frame *> used_list; std::list<Frame *> used_list;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Frame *item = bp_manager.alloc(); Frame *item = frame_manager.alloc();
ASSERT_NE(item, nullptr); ASSERT_NE(item, nullptr);
used_list.push_back(item); used_list.push_back(item);
} }
ASSERT_EQ(used_list.size(), bp_manager.get_used_num()); ASSERT_EQ(used_list.size(), frame_manager.get_used_num());
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Frame *item = bp_manager.alloc(); Frame *item = frame_manager.alloc();
ASSERT_EQ(item, nullptr); ASSERT_EQ(item, nullptr);
} }
...@@ -86,26 +86,26 @@ void test_alloc(BPManager &bp_manager) ...@@ -86,26 +86,26 @@ void test_alloc(BPManager &bp_manager)
Frame *item = used_list.front(); Frame *item = used_list.front();
used_list.pop_front(); used_list.pop_front();
bp_manager.free(item); frame_manager.free(item);
} else { } else {
Frame *item = bp_manager.alloc(); Frame *item = frame_manager.alloc();
used_list.push_back(item); used_list.push_back(item);
} }
ASSERT_EQ(used_list.size(), bp_manager.get_used_num()); ASSERT_EQ(used_list.size(), frame_manager.get_used_num());
} }
} }
TEST(test_bp_manager, test_bp_manager_simple_lru) TEST(test_frame_manager, test_frame_manager_simple_lru)
{ {
BPManager bp_manager("Test"); BPFrameManager frame_manager("Test");
bp_manager.init(false, 2); frame_manager.init(false, 2);
test_get(bp_manager); test_get(frame_manager);
test_alloc(bp_manager); test_alloc(frame_manager);
bp_manager.cleanup(); frame_manager.cleanup();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
...@@ -117,4 +117,4 @@ int main(int argc, char **argv) ...@@ -117,4 +117,4 @@ int main(int argc, char **argv)
// 调用RUN_ALL_TESTS()运行所有测试用例 // 调用RUN_ALL_TESTS()运行所有测试用例
// main函数返回RUN_ALL_TESTS()的运行结果 // main函数返回RUN_ALL_TESTS()的运行结果
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
\ No newline at end of file
...@@ -321,20 +321,11 @@ TEST(test_bplus_tree, test_leaf_index_node_handle) ...@@ -321,20 +321,11 @@ TEST(test_bplus_tree, test_leaf_index_node_handle)
index_file_header.attr_type = INTS; index_file_header.attr_type = INTS;
Frame frame; Frame frame;
frame.dirty = false;
frame.pin_count = 0;
frame.acc_time = 0;
frame.file_desc = 0;
frame.page.page_num = 100;
BPPageHandle page_handle;
page_handle.open = true;
page_handle.frame = &frame;
KeyComparator key_comparator; KeyComparator key_comparator;
key_comparator.init(INTS, 4); key_comparator.init(INTS, 4);
LeafIndexNodeHandler leaf_node(index_file_header, page_handle); LeafIndexNodeHandler leaf_node(index_file_header, &frame);
leaf_node.init_empty(); leaf_node.init_empty();
ASSERT_EQ(0, leaf_node.size()); ASSERT_EQ(0, leaf_node.size());
...@@ -389,20 +380,11 @@ TEST(test_bplus_tree, test_internal_index_node_handle) ...@@ -389,20 +380,11 @@ TEST(test_bplus_tree, test_internal_index_node_handle)
index_file_header.attr_type = INTS; index_file_header.attr_type = INTS;
Frame frame; Frame frame;
frame.dirty = false;
frame.pin_count = 0;
frame.acc_time = 0;
frame.file_desc = 0;
frame.page.page_num = 100;
BPPageHandle page_handle;
page_handle.open = true;
page_handle.frame = &frame;
KeyComparator key_comparator; KeyComparator key_comparator;
key_comparator.init(INTS, 4); key_comparator.init(INTS, 4);
InternalIndexNodeHandler internal_node(index_file_header, page_handle); InternalIndexNodeHandler internal_node(index_file_header, &frame);
internal_node.init_empty(); internal_node.init_empty();
ASSERT_EQ(0, internal_node.size()); ASSERT_EQ(0, internal_node.size());
...@@ -480,8 +462,6 @@ TEST(test_bplus_tree, test_scanner) ...@@ -480,8 +462,6 @@ TEST(test_bplus_tree, test_scanner)
{ {
LoggerFactory::init_default("test.log"); LoggerFactory::init_default("test.log");
DiskBufferPool::set_pool_num(POOL_NUM);
const char *index_name = "scanner.btree"; const char *index_name = "scanner.btree";
::remove(index_name); ::remove(index_name);
handler = new BplusTreeHandler(); handler = new BplusTreeHandler();
...@@ -689,10 +669,7 @@ TEST(test_bplus_tree, test_scanner) ...@@ -689,10 +669,7 @@ TEST(test_bplus_tree, test_scanner)
TEST(test_bplus_tree, test_bplus_tree_insert) TEST(test_bplus_tree, test_bplus_tree_insert)
{ {
LoggerFactory::init_default("test.log"); LoggerFactory::init_default("test.log");
// set the disk buffer pool's number to make it is easy to test
DiskBufferPool::set_pool_num(POOL_NUM);
::remove(index_name); ::remove(index_name);
handler = new BplusTreeHandler(); handler = new BplusTreeHandler();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册