Project #0
待补充
Project #1
Task 1
- timestamp, 要用最精确的nanosecond。
Task 2
- unpinPage一个难以想到的case:unpinPage是有is_dirty作为参数的。但是,不要直接根据is_dirty改变is_dirty_:userA call unpinPage(1, true), userB call unpinPage(1, false). 此时直接设置的话,page就变回了false,明显是不合逻辑的。
- rwlatch的设置,要非常小心,并且它们其实是同一个mutex!也就是说,没释放一个之前,是不能获得另一个的。
- 函数之间的相互调用,要避免,因为几乎每一个都用了某个可能冲突的lock。
- 续上,一个不明显的相互调用是 *this = BasicPageGuard(nullptr, nullptr); 【注意等于号】
Task 3
- 依旧注意lock的使用。如果某个函数需要某个lock,一定要提前释放这个lock。
- 因为move constructor要求另一个/之前的page不要再guard了,所以记得drop它们。
-
BasicPageGuard::BasicPageGuard(BasicPageGuard &&that) noexcept vs
auto BasicPageGuard::operator=(BasicPageGuard &&that) noexcept
-> BasicPageGuard &: 第一个是BPG bar = std::move(foo)时调用,另一个是BPG bar; bar = std::move(foo)时调用
-
c++的mutex,如果不是lock的,unlock会导致Undefined Behavior【crash, produce incorrect results, or have other unpredictable behavior】
-
debug很久的一个问题,,,一开始我没注意page table,因此我在bpm里面会访问每一个page,以此来寻找page的frame。问题出现在WriteGuard的operator constructor里面。
-
page的pin count,不要加page的写锁!
Project #2
【插播一个个人觉得很不错的设计模式:page拿data,有两个函数As和AsMut,其中AsMut会把page标记为dirty。巧妙的地方是As会返回const,防止用As之后不小心改了page】
- template class cannot find definition问题,注意include cpp,不是hhttps://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
- 一个奇怪的address points to the zero page的bug。后来发现是因为前面调用了move把本来的搞没了
-
不要:page_id_t* cur_new_page_id = nullptr; bpm_->NewPage(cur_new_page_id);
-
要:
-
use 'template' keyword to treat 'AsMut' as a dependent template name: 把auto改成对应的类型 【c++ - Confusing Template error - Stack Overflow】
-
xxx.first, xxx.second 可以用std::make_pair替代
-
卡死的问题
-
不要用NewPage之类的函数!!上一个proj写的guard是干嘛用的。
-
过本地test并不难。笔者困扰的bug最终原因是二分法找index的细节和next page id处理。
-
deque的反向遍历问题。必须用rbegin rend
-
not rend, but rend-1
-
一个lock不会死锁。
-
打印lock地址,检查lock是不是没了!
-
首先,evict会导致内存变化。因此如果一个page指针不用guard的话,它在后文很有可能变了,就没法用了。再有,bpm_->FetchPageWrite(new_internal_page_id).AsMut<B_PLUS_TREE_INTERNAL_PAGE_TYPE_PID>()。这里拿到的Guard也是会当场释放。
-
从14可以看出,需要处处留心guard的存在。比如我的iterator里面用的page的指针,这里又导致了错误。解决方法是改成用page id。再比如其他一些函数,返回的是page指针,同样有问题。
Project #3
我最后一个topn用了heap。多次出bug才发现heap的机制不是完全排好序,它只能保证pop的东西是最大/最小的。因此topn用priority queue会更好。
Project #4
- 两个头文件相互需要对方的问题(或者说两个class的member互相需要对方)会导致编译失败,error:unknown type name。原因见链接c++ - Resolve build errors due to circular dependency amongst classes - Stack Overflow
- cv.wait()的用法。wait会阻塞运行,并且释放这个锁。notify用来提醒wait去检查是否可以恢复运行了。相当于channel。第二个参数pred是FunctionObject,FunctionObject是不要括号的,即它的调用方法是加括号
- deadlock怎么调试:lldb里面control+C,命令thread bt all可以看到所有thread卡在哪里