Untitled
unknown
c_cpp
a year ago
6.7 kB
7
Indexable
//===----------------------------------------------------------------------===// // // BusTub // // buffer_pool_manager.cpp // // Identification: src/buffer/buffer_pool_manager.cpp // // Copyright (c) 2015-2021, Carnegie Mellon University Database Group // //===----------------------------------------------------------------------===// #include "buffer/buffer_pool_manager.h" #include "common/exception.h" #include "common/macros.h" #include "storage/disk/disk_scheduler.h" #include "storage/page/page_guard.h" namespace bustub { BufferPoolManager::BufferPoolManager(size_t pool_size, DiskManager *disk_manager, size_t replacer_k, LogManager *log_manager) : pool_size_(pool_size), disk_scheduler_(std::make_unique<DiskScheduler>(disk_manager)), log_manager_(log_manager) { // TODO(students): remove this line after you have implemented the buffer pool manager // throw NotImplementedException( // "BufferPoolManager is not implemented yet. If you have finished implementing BPM, please remove the throw " // "exception line in `buffer_pool_manager.cpp`."); // we allocate a consecutive memory space for the buffer pool pages_ = new Page[pool_size_]; replacer_ = std::make_unique<LRUKReplacer>(pool_size, replacer_k); // 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)); } } BufferPoolManager::~BufferPoolManager() { delete[] pages_; } auto BufferPoolManager::NewPage(page_id_t *page_id) -> Page * { std::lock_guard<std::mutex> lock(latch_); // std::cout << "NewPage" << std::endl; if (!free_list_.empty()) { // first check free_list_ // std::cout << "Test 1" << std::endl; frame_id_t frame_id = free_list_.front(); free_list_.pop_front(); *page_id = this->AllocatePage(); Page *new_page = &pages_[frame_id]; new_page->page_id_ = *page_id; new_page->is_dirty_ = false; new_page->pin_count_ = 1; page_table_[*page_id] = frame_id; replacer_->RecordAccess(frame_id); replacer_->SetEvictable(frame_id, false); // std::cout << "NewPage ends" << std::endl; return new_page; } // std::cout << "Test 2" << std::endl; frame_id_t frame_id; if (!replacer_->Evict(&frame_id)) { // no page evictable // std::cout << "NewPage ends" << std::endl; return nullptr; } // std::cout << "Test 3" << std::endl; Page *old_page = &pages_[frame_id]; if (old_page->IsDirty()) { // std::cout << "FLUSH!!!" << std::endl; this->FlushPage(old_page->GetPageId()); // deadlock!!!!!!!!!! } // std::cout << "Test 4" << std::endl; *page_id = this->AllocatePage(); Page *new_page = &pages_[frame_id]; new_page->page_id_ = *page_id; new_page->is_dirty_ = false; new_page->pin_count_ = 1; page_table_.erase(old_page->GetPageId()); // ??????? std::cout << "remove " << old_page->GetPageId() << std::endl; page_table_[*page_id] = frame_id; replacer_->RecordAccess(frame_id); replacer_->SetEvictable(frame_id, false); // std::cout << "NewPage ends" << std::endl; return new_page; } auto BufferPoolManager::FetchPage(page_id_t page_id, [[maybe_unused]] AccessType access_type) -> Page * { std::lock_guard<std::mutex> lock(latch_); if (page_table_.find(page_id) != page_table_.end()) { // already in the buffer pool std::cout << "already in the buffer pool" << std::endl; frame_id_t frame_id = page_table_[page_id]; Page *page = &pages_[frame_id]; page->pin_count_++; replacer_->RecordAccess(frame_id); replacer_->SetEvictable(frame_id, false); return page; } if (!free_list_.empty()) { std::cout << "found free list in FetchPage" << std::endl; // frame_id_t frame_id = free_list_.front(); free_list_.pop_front(); DiskRequest r; r.is_write_ = false; r.page_id_ = page_id; auto promise1 = disk_scheduler_->CreatePromise(); // disk_scheduler_->Schedule(r); } std::cout << "cannot find free list in FetchPage" << std::endl; frame_id_t frame_id; if (!replacer_->Evict(&frame_id)) { // no page evictable return nullptr; } return nullptr; } auto BufferPoolManager::UnpinPage(page_id_t page_id, bool is_dirty, [[maybe_unused]] AccessType access_type) -> bool { std::lock_guard<std::mutex> lock(latch_); if (page_table_.find(page_id) == page_table_.end()) { return false; } frame_id_t frame_id = page_table_[page_id]; Page *page = &pages_[frame_id]; if (page->pin_count_ == 0) { return false; } page->pin_count_--; if (page->pin_count_ == 0) { replacer_->SetEvictable(frame_id, true); } // set the dirty flag on the page to indicate if the page was modified??? page->is_dirty_ = is_dirty; return true; } auto BufferPoolManager::FlushPage(page_id_t page_id) -> bool { // std::lock_guard<std::mutex> lock(latch_); // ?????? if (page_table_.find(page_id) != page_table_.end()) { frame_id_t frame_id = page_table_[page_id]; Page *page = &pages_[frame_id]; // Use the DiskManager::WritePage() method to flush a page to disk disk_scheduler_->disk_manager_->WritePage(page_id, page->GetData()); page->is_dirty_ = false; return true; } return false; } void BufferPoolManager::FlushAllPages() { std::lock_guard<std::mutex> lock(latch_); for (size_t i = 0; i < pool_size_; i++) { Page *page = &pages_[i]; // this->FlushPage(page->GetPageId()); disk_scheduler_->disk_manager_->WritePage(page->GetPageId(), page->GetData()); page->is_dirty_ = false; } } auto BufferPoolManager::DeletePage(page_id_t page_id) -> bool { std::lock_guard<std::mutex> lock(latch_); if (page_table_.find(page_id) == page_table_.end()) { return true; } frame_id_t frame_id = page_table_[page_id]; Page *page = &pages_[frame_id]; if (page->pin_count_ > 0) { return false; } page_table_.erase(page_id); replacer_->Remove(frame_id); free_list_.push_back(frame_id); page->is_dirty_ = false; page->pin_count_ = 0; page->ResetMemory(); // Call DeallocatePage() ????? DeallocatePage(page_id); return true; } auto BufferPoolManager::AllocatePage() -> page_id_t { return next_page_id_++; } auto BufferPoolManager::FetchPageBasic(page_id_t page_id) -> BasicPageGuard { return {this, nullptr}; } auto BufferPoolManager::FetchPageRead(page_id_t page_id) -> ReadPageGuard { return {this, nullptr}; } auto BufferPoolManager::FetchPageWrite(page_id_t page_id) -> WritePageGuard { return {this, nullptr}; } auto BufferPoolManager::NewPageGuarded(page_id_t *page_id) -> BasicPageGuard { return {this, nullptr}; } } // namespace bustub
Editor is loading...