cmu15445 2023fall project2

cmu2023 fall project 2

project2

task1:page_guard

#include "storage/page/page_guard.h"
#include "buffer/buffer_pool_manager.h"

namespace bustub {
//noexcept表示该函数不会抛出异常
BasicPageGuard::BasicPageGuard(BasicPageGuard &&that) noexcept {
  bpm_ = that.bpm_;
  page_ = that.page_;
  that.page_ = nullptr;
  that.bpm_ = nullptr;
}

void BasicPageGuard::Drop() {
  if(page_!= nullptr){
    if(is_dirty_){
      bpm_->UnpinPage(page_->GetPageId(), is_dirty_);
    } else{
      bpm_->UnpinPage(page_->GetPageId(), false);
    }
    page_ = nullptr;
    is_dirty_ = false;
  }
}

auto BasicPageGuard::operator=(BasicPageGuard &&that) noexcept -> BasicPageGuard & {
  if (this != &that) {
    Drop();
    bpm_ = that.bpm_;
    page_ = that.page_;
    is_dirty_ = that.is_dirty_;
    that.bpm_ = nullptr;
    that.page_ = nullptr;
    that.is_dirty_ = false;
  }
  return *this;
}

BasicPageGuard::~BasicPageGuard(){
  Drop();
};  // NOLINT

ReadPageGuard::ReadPageGuard(ReadPageGuard &&that) noexcept {
  guard_ = std::move(that.guard_);
}

auto ReadPageGuard::operator=(ReadPageGuard &&that) noexcept -> ReadPageGuard & {
  if (this != &that) {
    guard_ = std::move(that.guard_);
  }
  return *this;
}

void ReadPageGuard::Drop() {
  guard_.Drop();
}

ReadPageGuard::~ReadPageGuard() {
  Drop();
}  // NOLINT

WritePageGuard::WritePageGuard(WritePageGuard &&that) noexcept{
  guard_ = std::move(that.guard_);
}

auto WritePageGuard::operator=(WritePageGuard &&that) noexcept -> WritePageGuard & {
  if (this != &that) {
    guard_ = std::move(that.guard_);
  }
  return *this;
}

void WritePageGuard::Drop() {
  guard_.Drop();
}

WritePageGuard::~WritePageGuard() {
  Drop();
}  // NOLINT

}  // namespace bustub

task2

1、extendible_htable_header_page.cpp

//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// extendible_htable_header_page.cpp
//
// Identification: src/storage/page/extendible_htable_header_page.cpp
//
// Copyright (c) 2015-2023, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "storage/page/extendible_htable_header_page.h"

#include "common/exception.h"

namespace bustub {

void ExtendibleHTableHeaderPage::Init(uint32_t max_depth) {
  max_depth_ = max_depth;
  // 初始化目录页ID数组,将所有值设为无效ID
  auto size = MaxSize();
  for (uint32_t i = 0; i < size; ++i) {
    directory_page_ids_[i] = INVALID_PAGE_ID;
  }
}

auto ExtendibleHTableHeaderPage::HashToDirectoryIndex(uint32_t hash) const -> uint32_t {
  if (max_depth_ == 0) {
    return 0;
  }
  // 取开头的max_depth_个二进制数
  return hash >> (sizeof(hash)*8 - max_depth_);
}

auto ExtendibleHTableHeaderPage::GetDirectoryPageId(uint32_t directory_idx) const -> uint32_t {
  if (directory_idx >= static_cast<uint32_t>(1 << max_depth_)) {
    throw Exception("Directory index out of bound");
  }
  return directory_page_ids_[directory_idx];
}

void ExtendibleHTableHeaderPage::SetDirectoryPageId(uint32_t directory_idx, page_id_t directory_page_id) {
  if (directory_idx >= static_cast<uint32_t>(1 << max_depth_)) {
    throw Exception("Directory index out of bound");
  }
  directory_page_ids_[directory_idx] = directory_page_id;
}

auto ExtendibleHTableHeaderPage::MaxSize() const -> uint32_t {
  //用了移位运算符 << 来计算 2^max_depth_,对于任何整数 x,1 << x 的结果是 2^x。
  return 1 << max_depth_;
}

}  // namespace bustub

2、extendible_htable_directory_page.cpp

//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// extendible_htable_directory_page.cpp
//
// Identification: src/storage/page/extendible_htable_directory_page.cpp
//
// Copyright (c) 2015-2023, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "storage/page/extendible_htable_directory_page.h"

#include <algorithm>
#include <unordered_map>

#include "common/config.h"
#include "common/logger.h"

namespace bustub {

auto ExtendibleHTableDirectoryPage::GetGlobalDepthMask() const -> uint32_t {
  // 计算掩码,全局深度位的低位是 1,其余位是 0
  // 例如,如果全局深度为 2,则掩码是二进制的 11(即十进制的 3)
  auto depth = global_depth_;
  uint32_t result = (1 << depth) - 1;
  return result;
}

auto ExtendibleHTableDirectoryPage::GetLocalDepthMask(uint32_t bucket_idx) const -> uint32_t {
  // 首先检查 bucket_idx 是否有效
  if (bucket_idx >= static_cast<uint32_t>(1 << global_depth_)) {
    throw std::out_of_range("Bucket index out of range");
  }
  // 获取 bucket_idx 处的局部深度
  uint32_t local_depth = local_depths_[bucket_idx];
  // 计算掩码,局部深度位的低位是 1,其余位是 0
  return 1 << (local_depth - 1);
}

void ExtendibleHTableDirectoryPage::Init(uint32_t max_depth) {
  max_depth_ = max_depth;
  global_depth_ = 0;
  std::fill(local_depths_, local_depths_ + (1 << max_depth), 0);
  std::fill(bucket_page_ids_, bucket_page_ids_ + (1 << max_depth), INVALID_PAGE_ID);
}

auto ExtendibleHTableDirectoryPage::HashToBucketIndex(uint32_t hash) const -> uint32_t {
  //先交 GlobalDepthMask、后交LocalDepthMask。
  auto hash_ = hash & GetGlobalDepthMask();
  return hash_;
}

auto ExtendibleHTableDirectoryPage::GetBucketPageId(uint32_t bucket_idx) const -> page_id_t {
  return bucket_page_ids_[bucket_idx];
}

void ExtendibleHTableDirectoryPage::SetBucketPageId(uint32_t bucket_idx, page_id_t bucket_page_id) {
  bucket_page_ids_[bucket_idx] = bucket_page_id;
}

auto ExtendibleHTableDirectoryPage::GetSplitImageIndex(uint32_t bucket_idx) const -> uint32_t {
  // 获取桶的本地深度
  uint32_t local_depth = GetLocalDepth(bucket_idx);

  // 计算和本地深度对应的位掩码
  uint32_t mask = 1 << local_depth;

  // 计算分裂的镜像索引
  return bucket_idx ^ mask;
}

auto ExtendibleHTableDirectoryPage::GetGlobalDepth() const -> uint32_t {
  return global_depth_;
}

void ExtendibleHTableDirectoryPage::IncrGlobalDepth() {
  // 增加全局深度

  global_depth_++;
  // 计算新的目录大小
  uint32_t new_size = 1 << global_depth_;
  uint32_t old_size = new_size >> 1;  // 或者等于 1 << (global_depth_ - 1)
  // 更新目录项
  for (uint32_t i = 0; i < old_size; ++i) {
    // 新的目录项是旧目录项的复制
    bucket_page_ids_[old_size + i] = bucket_page_ids_[i];
    local_depths_[old_size + i] = local_depths_[i];
  }

}

void ExtendibleHTableDirectoryPage::DecrGlobalDepth() {
  if (global_depth_ > 0) {
    global_depth_--;
  }
}

auto ExtendibleHTableDirectoryPage::CanShrink() -> bool {
  // 如果全局深度为0,则不能再收缩
  if (global_depth_ == 0) {
    return false;
  }
  // 检查所有桶的本地深度是否都小于全局深度
  for (uint32_t i = 0; i < Size(); i++) {
    if (local_depths_[i] == global_depth_) {
      return false;
    }
  }
  return true;
}

auto ExtendibleHTableDirectoryPage::Size() const -> uint32_t {
  // 目录的当前大小是2的global_depth_次方
  return 1 << global_depth_;
}

auto ExtendibleHTableDirectoryPage::GetLocalDepth(uint32_t bucket_idx) const -> uint32_t {
  return local_depths_[bucket_idx];
}

void ExtendibleHTableDirectoryPage::SetLocalDepth(uint32_t bucket_idx, uint8_t local_depth) {
    auto depth __attribute__((unused)) = local_depths_[bucket_idx];
    local_depths_[bucket_idx] = local_depth;
}

void ExtendibleHTableDirectoryPage::IncrLocalDepth(uint32_t bucket_idx) {
  if (local_depths_[bucket_idx] < global_depth_) {
    local_depths_[bucket_idx]++;
  }

}

void ExtendibleHTableDirectoryPage::DecrLocalDepth(uint32_t bucket_idx) {
  if (local_depths_[bucket_idx] > 0) {
    local_depths_[bucket_idx]--;
  }
}

}  // namespace bustub

3、extendible_htable_bucket_page.cpp

//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// extendible_htable_bucket_page.cpp
//
// Identification: src/storage/page/extendible_htable_bucket_page.cpp
//
// Copyright (c) 2015-2023, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <optional>
#include <utility>

#include "common/exception.h"
#include "storage/page/extendible_htable_bucket_page.h"

namespace bustub {

template <typename K, typename V, typename KC>
void ExtendibleHTableBucketPage<K, V, KC>::Init(uint32_t max_size) {
  size_ = 0;
  max_size_ = max_size;
  // array_ 的初始化依赖于 KeyValue 类型的大小和页面大小限制
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::Lookup(const K &key, V &value, const KC &cmp) const -> bool {
  for (uint32_t i = 0; i < size_; ++i) {
    if (cmp(array_[i].first, key) == 0) {
      value = array_[i].second;
      return true;
    }
  }
  return false;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::Insert(const K &key, const V &value, const KC &cmp) -> bool {
  if (IsFull()) {
    return false;
  }
  // 检查键是否已存在
  for (uint32_t i = 0; i < size_; ++i) {
    if (cmp(array_[i].first, key) == 0) {
      return false;  // 该键已存在
    }
  }
  // 插入新的键值对
  array_[size_++] = std::make_pair(key, value);
  return true;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::Remove(const K &key, const KC &cmp) -> bool {
  for (uint32_t i = 0; i < size_; ++i) {
    if (cmp(array_[i].first, key) == 0) {
      // 找到键并删除
      for (uint32_t j = i + 1; j < size_; ++j) {
        array_[j - 1] = array_[j];
      }
      size_--;
      return true;
    }
  }
  return false;
}

template <typename K, typename V, typename KC>
void ExtendibleHTableBucketPage<K, V, KC>::RemoveAt(uint32_t bucket_idx) {
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::KeyAt(uint32_t bucket_idx) const -> K {
  return array_[bucket_idx].first;;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::ValueAt(uint32_t bucket_idx) const -> V {
  return array_[bucket_idx].second;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::EntryAt(uint32_t bucket_idx) const -> const std::pair<K, V> & {
  return array_[bucket_idx];;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::Size() const -> uint32_t {
  return size_;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::IsFull() const -> bool {
  return size_ >= max_size_;
}

template <typename K, typename V, typename KC>
auto ExtendibleHTableBucketPage<K, V, KC>::IsEmpty() const -> bool {
  return size_ == 0;
}

template class ExtendibleHTableBucketPage<int, int, IntComparator>;
template class ExtendibleHTableBucketPage<GenericKey<4>, RID, GenericComparator<4>>;
template class ExtendibleHTableBucketPage<GenericKey<8>, RID, GenericComparator<8>>;
template class ExtendibleHTableBucketPage<GenericKey<16>, RID, GenericComparator<16>>;
template class ExtendibleHTableBucketPage<GenericKey<32>, RID, GenericComparator<32>>;
template class ExtendibleHTableBucketPage<GenericKey<64>, RID, GenericComparator<64>>;

}  // namespace bustub

task3

//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// disk_extendible_hash_table.cpp
//
// Identification: src/container/disk/hash/disk_extendible_hash_table.cpp
//
// Copyright (c) 2015-2023, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include "common/config.h"
#include "common/exception.h"
#include "common/logger.h"
#include "common/macros.h"
#include "common/rid.h"
#include "common/util/hash_util.h"
#include "container/disk/hash/disk_extendible_hash_table.h"
#include "storage/index/hash_comparator.h"
#include "storage/page/extendible_htable_bucket_page.h"
#include "storage/page/extendible_htable_directory_page.h"
#include "storage/page/extendible_htable_header_page.h"
#include "storage/page/page_guard.h"

namespace bustub {

template <typename K, typename V, typename KC>
DiskExtendibleHashTable<K, V, KC>::DiskExtendibleHashTable(const std::string &name, BufferPoolManager *bpm,
                                                           const KC &cmp, const HashFunction<K> &hash_fn,
                                                           uint32_t header_max_depth, uint32_t directory_max_depth,
                                                           uint32_t bucket_max_size)
    : bpm_(bpm),
      cmp_(cmp),
      hash_fn_(std::move(hash_fn)),
      header_max_depth_(header_max_depth),
      directory_max_depth_(directory_max_depth),
      bucket_max_size_(bucket_max_size) {
  this->index_name_ = name;
  //初始化header页
  header_page_id_ = INVALID_PAGE_ID;
  auto header_guard = bpm->NewPageGuarded(&header_page_id_);
  auto header_page = header_guard.AsMut<ExtendibleHTableHeaderPage>();
  header_page->Init(header_max_depth_);

  //初始化目录页
  page_id_t directory_page_id = INVALID_PAGE_ID;
  BasicPageGuard directory_guard = bpm->NewPageGuarded(&directory_page_id);
  auto directory_page = directory_guard.AsMut<ExtendibleHTableDirectoryPage>();
  directory_page->Init(directory_max_depth_);

  //初始化bucket页
  page_id_t bucket_page_id = INVALID_PAGE_ID;
  BasicPageGuard bucket_guard = bpm->NewPageGuarded(&bucket_page_id);
  auto bucket_page = bucket_guard.AsMut<ExtendibleHTableBucketPage<GenericKey<8>, RID, GenericComparator<8>>>();
  bucket_page->Init(bucket_max_size_);

  //连接header页和目录页
  header_page->SetDirectoryPageId(0, directory_page_id);
  directory_page->SetBucketPageId(0, bucket_page_id);
}

/*****************************************************************************
 * SEARCH
 *****************************************************************************/
template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::GetValue(const K &key, std::vector<V> *result, Transaction *transaction) const
    -> bool {
  //计算key的哈希值
  uint32_t hash = Hash(key);

  //先根据header_page_id_获取header页
  auto header_page_data = bpm_->FetchPage(header_page_id_);
  if (header_page_data == nullptr) {
    throw Exception("Failed to fetch header page");
  }
  // 获取header_page
  auto header_page = reinterpret_cast<ExtendibleHTableHeaderPage *>(header_page_data->GetData());

  //使用header_page来获取目录索引
  uint32_t directory_index = header_page->HashToDirectoryIndex(hash);
  //用目录索引获取目录页,然后找到目錄頁的ID
  page_id_t directory_page_id = header_page->GetDirectoryPageId(directory_index);
  bpm_->UnpinPage(header_page_id_, false); // 取消固定header_page


  auto directory_page_data = bpm_->FetchPage(directory_page_id);
  if (directory_page_data == nullptr) {
    throw Exception("Failed to fetch header page");
  }
  // 获取目录页
  auto directory_page = reinterpret_cast<ExtendibleHTableDirectoryPage *>(directory_page_data->GetData());
  //使用directory_page来获取目录索引
  auto bucket_index = directory_page->HashToBucketIndex(hash);
  // 根据目录索引找到桶页的ID
  page_id_t bucket_page_id = directory_page->GetBucketPageId(bucket_index);
  bpm_->UnpinPage(directory_page_id, false);// 取消固定directory_page_id


  //获取桶页并使用Lookup函数查找键
  auto bucket_page_data = bpm_->FetchPage(bucket_page_id);
  if (bucket_page_data == nullptr) {
    throw Exception("Failed to fetch bucket page");
  }
  auto bucket_page = reinterpret_cast<ExtendibleHTableBucketPage<K, V, KC> *>(bucket_page_data->GetData());

  V value;
  bool found = bucket_page->Lookup(key, value, cmp_);
  if (found) {
    result->push_back(value);
  }
  bpm_->UnpinPage(bucket_page_id, false); // 取消固定桶页

  return found;
}

/*****************************************************************************
 * INSERTION
 *****************************************************************************/

template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::Insert(const K &key, const V &value, Transaction *transaction) -> bool {
  //计算key的哈希值
  uint32_t hash = Hash(key);
  //先根据header_page_id_获取header页
  auto header_read_guard= bpm_->FetchPageRead(header_page_id_);
  auto header_page_data = bpm_->FetchPage(header_page_id_);
  if (header_page_data == nullptr) {
    throw Exception("Failed to fetch header page");
  }
  // 获取header_page
  auto header_page = reinterpret_cast<ExtendibleHTableHeaderPage *>(header_page_data->GetData());
  //使用header_page来获取目录索引
  auto directory_index = header_page->HashToDirectoryIndex(hash);
  //用目录索引获取目录页,然后找到目錄頁的ID
  page_id_t directory_page_id = header_page->GetDirectoryPageId(directory_index);
  header_page_data->RUnlatch();
  header_read_guard.Drop();
  bpm_->UnpinPage(header_page_id_, false); // 取消固定header_page

  auto directory_read_guard= bpm_->FetchPageRead(directory_page_id);
  auto directory_page_data = bpm_->FetchPage(directory_page_id);
  // 获取目录页
  auto directory_page = reinterpret_cast<ExtendibleHTableDirectoryPage *>(directory_page_data->GetData());

  //使用directory_page来获取目录索引
  auto bucket_index = directory_page->HashToBucketIndex(hash);
  // 根据目录索引找到桶页的ID
  page_id_t bucket_page_id = directory_page->GetBucketPageId(bucket_index);
  directory_page_data->RUnlatch();
  directory_read_guard.Drop();
  bpm_->UnpinPage(directory_page_id, false);// 取消固定directory_page_id

  auto bucket_page_data = bpm_->FetchPage(bucket_page_id);
  //获取桶页
  auto bucket_page = reinterpret_cast<ExtendibleHTableBucketPage<K, V, KC> *>(bucket_page_data->GetData());

  //進行插入鍵值
  bool insert_result = InsertToNewDirectory(header_page, directory_index, hash, key, value);
  //如果插入成功,将bucket_page_id写回目录页
  //插入不成功,检查是否需要扩展目录页
  if (insert_result) {
    bpm_->UnpinPage(bucket_page_id, true); // 标记为脏并取消固定桶页
  } else {
    // Step 1: 检查是否需要扩展全局目录
    if (directory_page->GetLocalDepth(bucket_index) == directory_page->GetGlobalDepth()) {
      // 需要扩展全局目录,因为全局深度等于局部深度
      if(directory_page->GetGlobalDepth() == directory_max_depth_){
        return false;
      }
      directory_page->IncrGlobalDepth();
    }
    // 进行桶分裂
    uint32_t original_bucket_idx = directory_page->HashToBucketIndex(hash);
    uint32_t split_bucket_idx = directory_page->GetSplitImageIndex(original_bucket_idx);
    //初始化新bucket页
    page_id_t new_bucket_page_id = INVALID_PAGE_ID;
    BasicPageGuard new_bucket_guard = bpm_->NewPageGuarded(&new_bucket_page_id);
    auto new_bucket_page = new_bucket_guard.AsMut<ExtendibleHTableBucketPage<K, V, KC>>();
    new_bucket_page->Init(bucket_max_size_);

    // 更新原始和新分裂桶的局部深度
    directory_page->IncrLocalDepth(original_bucket_idx);
    directory_page->SetLocalDepth(split_bucket_idx, directory_page->GetLocalDepth(original_bucket_idx));
    auto new_local_depth = directory_page->GetLocalDepth(original_bucket_idx);
    auto local_depth_mask = directory_page->GetLocalDepthMask(original_bucket_idx);
    directory_page->SetBucketPageId(split_bucket_idx, new_bucket_page_id);
    // 局部深度已经增加,且split_bucket_idx是新桶对应的目录索引,進行目錄更新
    UpdateDirectoryMapping(directory_page, split_bucket_idx, new_bucket_page_id, new_local_depth, local_depth_mask);

    //重新分配键到原桶和新桶
    auto size = bucket_page->Size();
    for (uint32_t i = 0; i < size; ++i) {
      // 将键值对分配到原桶和新桶
      auto bucket_key = bucket_page->KeyAt(i);
      uint32_t key_hash = Hash(bucket_key);
      uint32_t bucketIndex = directory_page->HashToBucketIndex(key_hash);
      // 确定是否应该在当前桶中
      if (split_bucket_idx == bucketIndex) {
        // 键应该存储在新桶中
        bucket_page->Remove(bucket_key,cmp_);
        new_bucket_page->Insert(bucket_page->KeyAt(i), bucket_page->ValueAt(i), cmp_);
      }
    }
    // 在分裂完成后,再次尝试插入
    insert_result = Insert(key, value);
  }
  // WritePageGuard的析构函数会自动处理页面的解固定和脏页写回操作
  return insert_result;

}

template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::InsertToNewDirectory(ExtendibleHTableHeaderPage *header, uint32_t directory_idx,
                                                             uint32_t hash, const K &key, const V &value) -> bool {
  // 计算新的目录索引,这里假设已经进行了全局深度的增加
  uint32_t new_directory_index = header->HashToDirectoryIndex(hash);

  // 获取新的目录页ID
  page_id_t new_directory_page_id = header->GetDirectoryPageId(new_directory_index);

  // 获取新的目录页
  auto new_directory_page_data = bpm_->FetchPage(new_directory_page_id);
  if (new_directory_page_data == nullptr) {
    throw Exception("Failed to fetch new directory page");
  }
  auto new_directory_page = reinterpret_cast<ExtendibleHTableDirectoryPage *>(new_directory_page_data->GetData());

  // 使用新的目录页进行插入
  uint32_t new_bucket_idx = new_directory_page->HashToBucketIndex(hash);
  bool insert_result = InsertToNewBucket(new_directory_page, new_bucket_idx, key, value);

  // 完成操作,释放页面
  bpm_->UnpinPage(new_directory_page_id, insert_result); // 如果插入成功,标记页面为脏
  return insert_result;
}

template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::InsertToNewBucket(ExtendibleHTableDirectoryPage *directory, uint32_t bucket_idx,
                                                          const K &key, const V &value) -> bool {
  // 获取桶页面ID
  page_id_t bucket_page_id = directory->GetBucketPageId(bucket_idx);
  // 获取桶页面

  auto bucket_page_data = bpm_->FetchPage(bucket_page_id);
  if (bucket_page_data == nullptr) {
    throw Exception("Failed to fetch bucket page");
  }
  auto bucket_page = reinterpret_cast<ExtendibleHTableBucketPage<K, V, KC> *>(bucket_page_data->GetData());
  // 尝试插入键值对
  bool insert_result = bucket_page->Insert(key, value, cmp_);

  // 完成操作,释放页面
  bpm_->UnpinPage(bucket_page_id, insert_result); // 如果插入成功,标记页面为脏

  return insert_result;
}

template <typename K, typename V, typename KC>
void DiskExtendibleHashTable<K, V, KC>::UpdateDirectoryMapping(ExtendibleHTableDirectoryPage *directory,
                                                               uint32_t new_bucket_idx, page_id_t new_bucket_page_id,
                                                               uint32_t new_local_depth, uint32_t local_depth_mask) {
  for (uint32_t i = 0; i < (1U << directory->GetGlobalDepth()); ++i) {
    // 检查目录条目是否需要更新为指向新桶
    // 如果目录项对应的是原桶
    if (directory->GetBucketPageId(i) == directory->GetBucketPageId(new_bucket_idx)) {
      if (i & local_depth_mask) {
        // 如果这个目录项的在新局部深度位上的值为1,应该指向新桶
        directory->SetBucketPageId(i, new_bucket_page_id);
        directory->SetLocalDepth(i, new_local_depth);
      } else {
        // 否则,它仍然指向原桶,但其局部深度需要更新
        directory->SetLocalDepth(i, new_local_depth);
      }
    }

  }
}

/*****************************************************************************
 * REMOVE
 *****************************************************************************/
template <typename K, typename V, typename KC>
auto DiskExtendibleHashTable<K, V, KC>::Remove(const K &key, Transaction *transaction) -> bool {
  //计算key的哈希值
  uint32_t hash = Hash(key);

  //先根据header_page_id_获取header页
  auto header_page_data = bpm_->FetchPage(header_page_id_);
  // 获取header_page
  auto header_page = reinterpret_cast<ExtendibleHTableHeaderPage *>(header_page_data->GetData());


  //使用header_page来获取目录索引
  auto directory_index = header_page->HashToDirectoryIndex(hash);
  //用目录索引获取目录页,然后找到目錄頁的ID
  page_id_t directory_page_id = header_page->GetDirectoryPageId(directory_index);
  if(directory_page_id == INVALID_PAGE_ID){
    return false;
  }
  bpm_->UnpinPage(header_page_id_, false); // 取消固定header_page

  auto directory_page_data = bpm_->FetchPage(directory_page_id);
  // 获取目录页
  auto directory_page = reinterpret_cast<ExtendibleHTableDirectoryPage *>(directory_page_data->GetData());
  //使用directory_page来获取目录索引
  auto bucket_index = directory_page->HashToBucketIndex(hash);
  // 根据目录索引找到桶页的ID
  page_id_t bucket_page_id = directory_page->GetBucketPageId(bucket_index);
  if(bucket_page_id == INVALID_PAGE_ID){
    return false;
  }
  bpm_->UnpinPage(directory_page_id, false);// 取消固定directory_page_id

  auto bucket_page_data = bpm_->FetchPage(bucket_page_id);
  //获取桶页
  auto bucket_page = reinterpret_cast<ExtendibleHTableBucketPage<K, V, KC> *>(bucket_page_data->GetData());
  if (bucket_page->Remove(key, cmp_)) {
    if(bucket_page->IsEmpty()) {
      bpm_->DeletePage(bucket_page_id);
      directory_page->DecrLocalDepth(bucket_index);
      auto split_index = directory_page->GetSplitImageIndex(bucket_index);
      if (directory_page->GetLocalDepth(split_index) == (directory_page->GetLocalDepth(bucket_index)+1)) {
        directory_page->DecrLocalDepth(split_index);
        for (uint32_t i = 0; i < (1U << directory_page->GetGlobalDepth()); ++i) {
          if (directory_page->GetBucketPageId(i) == bucket_page_id) {
            directory_page->SetBucketPageId(i, directory_page->GetBucketPageId(bucket_index));
          }
        }
        directory_page->SetBucketPageId(bucket_index, INVALID_PAGE_ID);
        bpm_->DeletePage(bucket_page_id);
        bpm_->UnpinPage(directory_page_id, false);
      }
      if (directory_page->CanShrink()) {
        // 如果目录页可以收缩,那么就收缩
        auto ole_global_depth = directory_page->GetGlobalDepth();
        directory_page->DecrGlobalDepth();
        auto new_global_depth = directory_page->GetGlobalDepth();
        for (uint32_t i = (1U << new_global_depth); i < (1U << ole_global_depth); ++i) {
          directory_page->SetBucketPageId(i, INVALID_PAGE_ID);
        }
      }
    }
    // 如果成功删除,标记页面为脏
    bpm_->UnpinPage(bucket_page_id, true);
    return true;
  }
  return false;
}

template class DiskExtendibleHashTable<int, int, IntComparator>;
template class DiskExtendibleHashTable<GenericKey<4>, RID, GenericComparator<4>>;
template class DiskExtendibleHashTable<GenericKey<8>, RID, GenericComparator<8>>;
template class DiskExtendibleHashTable<GenericKey<16>, RID, GenericComparator<16>>;
template class DiskExtendibleHashTable<GenericKey<32>, RID, GenericComparator<32>>;
template class DiskExtendibleHashTable<GenericKey<64>, RID, GenericComparator<64>>;
}  // namespace bustub

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值