CMU15-445 BUFFER POOL 实现思路整理

2021/02/08 12:16
阅读数 496

这个BUFFER Pool的lab题目有点像数据结构的设计

已经通过145/160的测试用例,还有一个testD没能通过

针对之前的做一些代码上的复用,增加几个函数

判断free-list和replacer均为空

  bool isAllPinned(){
    return free_list_.empty()&&replacer_->Size()==0;
  }

初始化新的page信息

  void InitNewPage(frame_id_t frame_id, page_id_t page_id){
    pages_[frame_id].page_id_ = page_id;
    pages_[frame_id].pin_count_ = 1;
    pages_[frame_id].is_dirty_ = false;
  }

从freelist或者replacer找一个page来替换

  frame_id_t FindReplace(){
    frame_id_t frame_id = -1;
    if(!free_list_.empty()){
      frame_id = free_list_.front();
      free_list_.pop_front();
    }else if(replacer_->Size()>0){
      replacer_->Victim(&frame_id);
      page_table_.erase(pages_[frame_id].page_id_);
      if(pages_[frame_id].is_dirty_){
        disk_manager_->WritePage(pages_[frame_id].page_id_,pages_[frame_id].GetData());
      }
    }
    return frame_id;
  }

FetchPage实现

Page *BufferPoolManager::FetchPageImpl(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.
  std::scoped_lock bpm_slk{latch_};
  if(page_table_.find(page_id)!=page_table_.end()){
    auto frame_id = page_table_[page_id];
    pages_[frame_id].pin_count_++;
    replacer_->Pin(frame_id);
    return &pages_[frame_id];
  }
  if(!isAllPinned()){
    auto frame_id = FindReplace();
    page_table_[page_id] = frame_id;
    InitNewPage(frame_id,page_id);
    disk_manager_->ReadPage(page_id,pages_[frame_id].GetData());
    return &pages_[frame_id];
  }
  return nullptr;
}

UnpinPage实现

bool BufferPoolManager::UnpinPageImpl(page_id_t page_id, bool is_dirty) {
  std::scoped_lock bpm_slk{latch_};
  if(page_table_.find(page_id)==page_table_.end()){return false;}
  auto frame_id = page_table_[page_id];
  auto page = pages_ + frame_id;
  if(page->pin_count_<0){return false;}
  if(page->pin_count_>0) {
    page->pin_count_--;
  }
  if(page->pin_count_==0){
    replacer_->Unpin(frame_id);
  }
  page->is_dirty_ |= is_dirty;
  return true;
}

FlushPage实现 

bool BufferPoolManager::FlushPageImpl(page_id_t page_id) {
  //std::scoped_lock bpm_slk{latch_};
  // Make sure you call DiskManager::WritePage!
  if(page_table_.find(page_id)==page_table_.end()){
    return false;
  }
  auto frame_id = page_table_[page_id];
  auto page = pages_ + frame_id;
  disk_manager_->WritePage(page_id,page->GetData());
  page->is_dirty_ = false;
  return true;
}

NewPage

Page *BufferPoolManager::NewPageImpl(page_id_t *page_id) {
  // 0.   Make sure you call DiskManager::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::scoped_lock bpm_slk{latch_};
  auto new_page_id = disk_manager_->AllocatePage();
  if(isAllPinned()){
    return nullptr;
  }
  auto frame_id = FindReplace();
  page_table_[new_page_id] = frame_id;
  InitNewPage(frame_id,new_page_id);
  pages_[frame_id].ResetMemory();
  *page_id = new_page_id;
  return &pages_[frame_id];
}

DeletePage

bool BufferPoolManager::DeletePageImpl(page_id_t page_id) {
  // 0.   Make sure you call DiskManager::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.
  std::scoped_lock bpm_slk{latch_};
  disk_manager_->DeallocatePage(page_id);
  if(page_table_.find(page_id)==page_table_.end()) { return true;}
  auto frame_id = page_table_[page_id];
  auto page = pages_ + frame_id;
  if(page->pin_count_>0){
    return false;
  }
  replacer_->Unpin(frame_id);
  page_table_.erase(page_id);
  page->page_id_ = INVALID_PAGE_ID;
  free_list_.push_back(frame_id);
  return true;
}

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部