//===----------------------------------------------------------------------===//
//
// BusTub
//
// buffer_pool_manager_instance.cpp
//
// Identification: src/buffer/buffer_pool_manager.cpp
//
// Copyright (c) 2015-2021, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include "buffer/buffer_pool_manager_instance.h"
#include "common/macros.h"
namespace bustub {
BufferPoolManagerInstance::BufferPoolManagerInstance(size_t pool_size, DiskManager *disk_manager,
LogManager *log_manager)
: BufferPoolManagerInstance(pool_size, 1, 0, disk_manager, log_manager) {}
BufferPoolManagerInstance::BufferPoolManagerInstance(size_t pool_size, uint32_t num_instances, uint32_t instance_index,
DiskManager *disk_manager, LogManager *log_manager)
: pool_size_(pool_size),
num_instances_(num_instances),
instance_index_(instance_index),
next_page_id_(instance_index),
disk_manager_(disk_manager),
log_manager_(log_manager) {
BUSTUB_ASSERT(num_instances > 0, "If BPI is not part of a pool, then the pool size should just be 1");
BUSTUB_ASSERT(
instance_index < num_instances,
"BPI index cannot be greater than the number of BPIs in the pool. In non-parallel case, index should just be 1.");
// We allocate a consecutive memory space for the buffer pool.
pages_ = new Page[pool_size_];
replacer_ = new LRUReplacer(pool_size);
// Initially, every page is in the free list.
for (size_t i = 0; i < pool_size_; ++i) {
free_list_.emplace_back(static_cast<int>(i));
}
}
BufferPoolManagerInstance::~BufferPoolManagerInstance() {
delete[] pages_;
delete replacer_;
}
bool BufferPoolManagerInstance::FlushPgImp(page_id_t page_id) {
// Make sure you call DiskManager::WritePage!
std::lock_guard<std::mutex> guard(latch_);
if (page_id == INVALID_PAGE_ID || page_table_.find(page_id) == page_table_.end()) {
return false;
}
Page &rp = pages_[page_table_.find(page_id)->second];
rp.RLatch();
disk_manager_->WritePage(page_id, rp.data_);
rp.RUnlatch();
return true;
}
void BufferPoolManagerInstance::FlushAllPgsImp() {
// You can do it!
std::lock_guard<std::mutex> guard(latch_);
for (auto &iterat : page_table_) {
Page &rp = pages_[iterat.second];
rp.RLatch();
disk_manager_->WritePage(rp.page_id_, rp.data_);
rp.RUnlatch();
}
}
Page *BufferPoolManagerInstance::NewPgImp(page_id_t *page_id) {
// 0. Make sure you call AllocatePage!
// 1. If all the pages in the buffer pool are pinned, return nullptr.
// 2. Pick a victim page P from either the free list or the replacer. Always pick from the free list first.
// 3. Update P's metadata, zero out memory and add P to the page table.
// 4. Set the page ID output parameter. Return a pointer to P.
std::lock_guard<std::mutex> guard(latch_);
*page_id = AllocatePage();
bool isAllPin = true;
for (size_t i = 0; i < pool_size_; ++i) {
if (pages_[i].page_id_ == INVALID_PAGE_ID || pages_[i].pin_count_ == 0) {
isAllPin = false;
break;
}
}
if (isAllPin) {
return nullptr;
}
frame_id_t frame_id = -1;
if (!free_list_.empty()) {
frame_id = free_list_.back();
free_list_.pop_back();
} else {
bool isVictim = replacer_->Victim(&frame_id);
if (!isVictim) {
return nullptr;
}
}
page_table_[*page_id] = frame_id;
pages_[frame_id].WLatch();
memset(pages_[frame_id].data_, 0, sizeof(char) * PAGE_SIZE);
pages_[frame_id].page_id_ = *page_id;
++pages_[frame_id].pin_count_;
pages_[frame_id].WUnlatch();
return nullptr;
}
Page *BufferPoolManagerInstance::FetchPgImp(page_id_t page_id) {
// 1. Search the page table for the requested page (P).
// 1.1 If P exists, pin it and return it immediately.
// 1.2 If P does not exist, find a replacement page (R) from either the free list or the replacer.
// Note that pages are always found from the free list first.
// 2. If R is dirty, write it back to the disk.
// 3. Delete R from the page table and insert P.
// 4. Update P's metadata, read in the page content from disk, and then return a pointer to P.
return nullptr;
}
bool BufferPoolManagerInstance::DeletePgImp(page_id_t page_id) {
// 0. Make sure you call DeallocatePage!
// 1. Search the page table for the requested page (P).
// 1. If P does not exist, return true.
// 2. If P exists, but has a non-zero pin-count, return false. Someone is using the page.
// 3. Otherwise, P can be deleted. Remove P from the page table, reset its metadata and return it to the free list.
return false;
}
bool BufferPoolManagerInstance::UnpinPgImp(page_id_t page_id, bool is_dirty) { return false; }
page_id_t BufferPoolManagerInstance::AllocatePage() {
const page_id_t next_page_id = next_page_id_;
next_page_id_ += num_instances_;
ValidatePageId(next_page_id);
return next_page_id;
}
void BufferPoolManagerInstance::ValidatePageId(const page_id_t page_id) const {
assert(page_id % num_instances_ == instance_index_); // allocated pages mod back to this BPI
}
} // namespace bustub
原创文章,作者:wdmbts,如若转载,请注明出处:https://blog.ytso.com/267705.html