diff --git a/report.md b/report.md index d0b31e6..e2b829e 100644 --- a/report.md +++ b/report.md @@ -62,8 +62,8 @@ 对于vlog文件,我们在内存中维护一个bitmap,用来表示每一个slot的使用情况,并在插入和GC删除kv时进行动态的分配和释放。对于vlog文件的GC,我们用一个后台线程来扫描所有vlog的discard计数器。当某些vlog的discard计数器超过某个阈值(比如1024),我们就对这些vlog文件进行GC过程,当GC完成之后将slot_page中的slot元数据进行更新,再将原来的vlog文件进行删除,GC过程就完成了。 ##### 2.2.1 相关代码文件 -- [`/db/db_impl.cc`](./db/db_impl.cc) -- [`/db/db_impl.h`](./db/db_impl.h) +- [`/db/db_impl.cc`](./db/db_impl.cc): 修改 DBImpl::Get, DBImpl::Put 和 DBImpl::Delete +- [`/db/db_impl.h`](./db/db_impl.h): 添加两个结构体 SlotPage *slot_page_; VlogSet *vlog_set_; - - [`/db/shared_lock.h`](./db/shared_lock.h) 定义了一个 SharedLock 类,用于实现读写锁机制,包含四种操作:soft_lock():获取共享读锁,确保在没有写操作时允许多个读操作并发进行;soft_unlock():释放共享读锁;hard_lock():获取独占写锁,确保只有当没有其他读写操作时,允许写入操作进行;hard_unlock():释放独占写锁。 - [`/db/slotpage.h`](./db/slotpage.h) @@ -79,6 +79,66 @@ - [`/test/db_test5.cc`](./test/db_test5.cc) - - [`CMakeLists.txt`](CMakeLists.txt):添加可执行文件 +##### 2.2.1 具体流程 +写入流程 +```` +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + // TODO(begin): allocate slot_num in slotpage and put value in vlog + + size_t slot_num = slot_page_->alloc_slot(); + struct slot_content sc; + vlog_set_->put_value(&sc.vlog_num, &sc.value_offset, val); + slot_page_->set_slot(slot_num, &sc); + + char data[sizeof(size_t)]; + memcpy(data, &slot_num, sizeof(size_t)); + Slice slot_val(data, sizeof(data)); + + return DB::Put(o, key, slot_val); + // TODO(end) +} +```` +1. 调用编码函数,将 val 编码为字符串 +2. 在 slot_page_ 中为 K-V 对分配一个 slot ,编号为 slot_num +3. 实例化 slot_content 结构体 sc +4. 以 sc 中的 vlog_num(vlog编号) 和 value_offset(在vlog中的偏移量) 为参数,将字符串写入 vlog 中 +5. 将 slot_content 中的内容赋值给 slot_num +6. 将 slot_num 作为 key 的 value 写入数据库中 + +读取流程 +```` +// TODO(begin): search the slotpage and get value from vlog + size_t slot_num = *(size_t *)value->c_str(); + struct slot_content sc; + std::string vlog_value; + slot_page_->get_slot(slot_num, &sc); + vlog_set_->get_value(sc.vlog_num, sc.value_offset, &vlog_value); + *value = vlog_value; + // TODO(end) +```` +1. 读取 key 对应的 value, 也就是 slot_num +2. 实例化 slot_content 结构体 sc +3. 根据 slot_num 从 slot_page_ 中读取 slot_content +4. 利用 sc 中的 vlog_num(vlog编号) 和 value_offset(在vlog中的偏移量) 从 vlog 中读取字符串 +5. 将字符串进行解码得到 value + +删除流程 +```` +// TODO(begin) + ReadOptions ro; + ro.verify_checksums = true; + ro.fill_cache = false; + ro.snapshot = nullptr; + std::string value; + Get(ro, key, &value); + size_t slot_num = *(size_t *)value.c_str(); + struct slot_content sc; + std::string vlog_value; + slot_page_->get_slot(slot_num, &sc); + vlog_set_->del_value(sc.vlog_num, sc.value_offset); + // TODO(end) +```` +1. 读取 key 对应 ### 锁机制 ### 3. 数据结构设计 @@ -129,7 +189,6 @@ 5. Get_Fields (待实现) #### 4.2 实现KV分离 -这里只展示和vlog以及GC无关的接口,vlog的创建,管理以及后台线程的GC设计到vlog等新数据结构的实现,较为复杂和庞大,这里不做展示。我们只列出与kv的插入有关的新接口: 1. 搜索slot_page文件: Status find_slot(const Slice& key, Slot *slot); 2. 搜索vlog文件: Status find_value(Slot *slot); 3. 分配新的slot: Status allocate_slot(Bitmap *map, uint64_t *s);