CMU 15-445/645 fall2024 p1

在服务器内按照 bustub 文档完成开发环境配置后,P1 主要实现了 Buffer Pool 的核心路径:替换器、异步磁盘调度、页面 Guard,以及 BufferPoolManager 的页面生命周期管理。和 P0 一样,public 指模板仓库远程,origin 指我自己的远程仓库,日常开发在本地仓库完成。

Git 命令

git pull public master # 拉取模板更新
git push origin main   # 推送本地提交

lru_k_replacer.cpp

lru_k_replacer.cpp 实现了 LRU-K 替换器(按 backward k-distance 选择 victim):

  • LRUKReplacer(...)src/buffer/lru_k_replacer.cpp:19 初始化容量、k 值和内部容器。
  • Evictsrc/buffer/lru_k_replacer.cpp:21 选择可驱逐帧:优先处理访问次数不足 k 次的帧,否则比较 backward k-distance,最终移除 victim 并更新可驱逐数量。
  • RecordAccesssrc/buffer/lru_k_replacer.cpp:75 记录访问时间戳,并维护每帧最近 k 次访问历史。
  • SetEvictablesrc/buffer/lru_k_replacer.cpp:89 切换帧可驱逐状态,同步更新 size
  • Removesrc/buffer/lru_k_replacer.cpp:112 删除指定帧(要求可驱逐)。
  • Sizesrc/buffer/lru_k_replacer.cpp:131 返回当前可驱逐帧数量。

disk_scheduler.cpp

disk_scheduler.cpp 实现了基于后台线程的异步磁盘调度:

  • DiskScheduler(...)src/storage/disk/disk_scheduler.cpp:18 启动 worker 线程。
  • ~DiskSchedulersrc/storage/disk/disk_scheduler.cpp:23 发送停止信号并 join,确保线程有序退出。
  • Schedulesrc/storage/disk/disk_scheduler.cpp:31 将读写请求入队(请求里带 promise 用于完成通知)。
  • StartWorkerThreadsrc/storage/disk/disk_scheduler.cpp:33 循环取队列任务,调用 DiskManager::ReadPage/WritePage,完成后设置 promise

page_guard.cpp

page_guard.cppRAII 管理页面 latchpin/unpin,避免资源泄漏:

  • ReadPageGuard 构造在 src/storage/page/page_guard.cpp:30,接管读锁页面。
  • Guard 的移动构造/赋值在 src/storage/page/page_guard.cpp:52src/storage/page/page_guard.cpp:79,保证所有权安全转移。
  • ReadPageGuard::Dropsrc/storage/page/page_guard.cpp:132 释放锁、减少 pin,并在合适时更新 replacer 状态。
  • WritePageGuard 构造在 src/storage/page/page_guard.cpp:173,接管写锁页面。
  • Guard 的移动构造/赋值在 src/storage/page/page_guard.cpp:196src/storage/page/page_guard.cpp:223
  • WritePageGuard::Dropsrc/storage/page/page_guard.cpp:284 做写路径释放,保证 dirty/pin/replacer 状态一致。

buffer_pool_manager.cpp

buffer_pool_manager.cpp 是 P1 主体,负责管理 frame/page 的完整生命周期:

  • FrameHeader::Resetsrc/buffer/buffer_pool_manager.cpp:44 重置 frame 元数据(包括 page_id_)。
  • ScheduleDiskWrite/Readsrc/buffer/buffer_pool_manager.cpp:109src/buffer/buffer_pool_manager.cpp:116 封装异步 IO 与等待逻辑。
  • FetchPagesrc/buffer/buffer_pool_manager.cpp:123 处理命中和缺页:命中则增加 pin 并记录访问;缺页则从 free list/replacer 选帧,必要时刷脏页,再读入目标页并更新页表。
  • NewPagesrc/buffer/buffer_pool_manager.cpp:194 分配新页号并绑定 frame,初始化页面与元数据。
  • DeletePagesrc/buffer/buffer_pool_manager.cpp:226 删除页面:被 pin 时返回失败;否则移除页表/replacer 项并回收 frame
  • CheckedWritePage / CheckedReadPagesrc/buffer/buffer_pool_manager.cpp:288src/buffer/buffer_pool_manager.cpp:320 返回 WritePageGuard/ReadPageGuard(失败返回 std::nullopt)。
  • FlushPagesrc/buffer/buffer_pool_manager.cpp:394 将单页写回磁盘并清除 dirty
  • FlushAllPagessrc/buffer/buffer_pool_manager.cpp:440 批量刷盘所有缓冲页。
  • GetPinCountsrc/buffer/buffer_pool_manager.cpp:479 读取页面 pin 次数,便于测试与调试。

生成提交包

1.打包(与这次通过的文件列表一致) rm -f project1-submission.zip zip project1-submission.zip
src/include/buffer/lru_k_replacer.h
src/buffer/lru_k_replacer.cpp
src/include/buffer/buffer_pool_manager.h
src/buffer/buffer_pool_manager.cpp
src/include/storage/disk/disk_scheduler.h
src/storage/disk/disk_scheduler.cpp
src/storage/page/page_guard.cpp
src/include/storage/page/page_guard.h

2.把签名文件加进 zip(首次会交互生成 GRADESCOPE.md) python3 gradescope_sign.py

3.检查提交包内容 unzip -l project1-submission.zip