CMU15-455 Project1 BufferPool實現改進

通過110/160的測試,還有少量問題需要解決。

 

理解什麼是Page的pin, unpin和LRU的pin,unpin含義不同

page的pin,count++, page的unpin count--

LRU的pin表示從Replace取出,unpin表示加入到LRU

 

FlushPageImpl 給定page_id,將對應的頁寫到磁盤上,這個沒什麼問題。FlushPageImpl不加鎖,而保證在調用的時候加鎖。

bool BufferPoolManager::FlushPageImpl(page_id_t page_id) {
  // 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;
}

DeletePage操作,記住當引用計數爲0時,執行Replace的Pin操作。

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_->Pin(frame_id);
  page_table_.erase(page_id);
  page->page_id_ = INVALID_PAGE_ID;
  free_list_.push_back(frame_id);
  disk_manager_->DeallocatePage(page_id);
  return true;
}

UnpinPageImpl  

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(is_dirty){
    FlushPageImpl(page_id);
  }
  if(page->pin_count_>0) {
    page->pin_count_--;
  }
  if(page->pin_count_==0){
    replacer_->Unpin(frame_id);
  }
  return true;
}

FetchPageImpl操作,注意在table中找到,pin以後,Replacer也要pin一次。 

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];
    auto page = pages_ + frame_id;
    page->pin_count_++;               // pin it
    replacer_->Pin(frame_id);         // replacer 也要pin
    return page;
  }
  if(free_list_.empty()&&replacer_->Size()==0) {
    return nullptr;
  }
  frame_id_t frame_id = -1;
  Page *page = nullptr;
  if(!free_list_.empty()){
    frame_id = free_list_.front();
    free_list_.pop_back();
    page = pages_ + frame_id;
  }else{
    replacer_->Victim(&frame_id);
    page = pages_ + frame_id;
    page_table_.erase(page->GetPageId());      // 淘汰
  }
  if(page->is_dirty_){                         // 把舊數據寫到磁盤上
    disk_manager_->WritePage(page->GetPageId(),page->GetData());
  }
  page_table_[page_id] = frame_id;
  page->page_id_ = page_id;
  page->ResetMemory();
  page->pin_count_ = 1;
  page->is_dirty_ = false;
  disk_manager_->ReadPage(page_id,page->data_); // 讀取新的數據
  return page;
}

創建新的一頁

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_};
  frame_id_t frame_id = -1;
  Page *page = nullptr;
  if(free_list_.empty()&&replacer_->Size()==0){
    return nullptr;
  }
  if(!free_list_.empty()){
    frame_id = free_list_.front();
    free_list_.pop_front();
    page = pages_ + frame_id;
  }else{
    replacer_->Victim(&frame_id);
    page = pages_ + frame_id;
    page_table_.erase(page->page_id_);
    if(page->is_dirty_){
      disk_manager_->WritePage(page->page_id_,page->data_);
    }
  }
  auto new_page_id = disk_manager_->AllocatePage();
  page_table_[new_page_id] = frame_id;
  page->ResetMemory();
  page->page_id_ = new_page_id;
  *page_id = page->page_id_;
  page->is_dirty_ = true;
  page->pin_count_ = 1;
  return page;
}

Flush All


void BufferPoolManager::FlushAllPagesImpl() {
  // You can do it!
  for(size_t i=0;i<pool_size_;i++){
    FlushPageImpl(pages_[i].page_id_);
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章