diff --git a/CMakeLists.txt b/CMakeLists.txt index 974f190..d210d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,10 @@ endif(BUILD_SHARED_LIBS) # Must be included before CMAKE_INSTALL_INCLUDEDIR is used. include(GNUInstallDirs) -add_library(leveldb) +add_library(leveldb + db/vlog_reader.h + db/vlog_writer.h + db/vlog_manager.h) target_sources(leveldb PRIVATE "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h" diff --git a/db/vlog_manager.h b/db/vlog_manager.h new file mode 100644 index 0000000..07d14d3 --- /dev/null +++ b/db/vlog_manager.h @@ -0,0 +1,68 @@ +#ifndef LEVELDB_VLOG_MANAGER_H +#define LEVELDB_VLOG_MANAGER_H + +#include +#include +#include +#include "leveldb/env.h" + +namespace leveldb { +namespace vlog { + +class VlogWriter; +class VlogReader; + +class VlogInfo { + private: + /* vlog 当前大小 */ + size_t size_; + /* vlog 当前若插入新 record 的偏移 */ + size_t head_; + /* vlog 当前过期的 record 数量 */ + uint64_t expired_count_; + + VlogReader* vlog_read_; + VlogWriter* vlog_write_; + + public: + VlogInfo() : size_(0), head_(0), expired_count_(0) {} + ~VlogInfo() = default; + + friend class VlogWriter; + friend class VlogReader; + friend class VlogManager; +}; + +class VlogManager { + public: + explicit VlogManager(uint64_t expired_threshold); + ~VlogManager() = default; + + /* 新建一个 vlog 并编号 */ + void AddVlog(uint64_t vlog_no); + /* 往当前活跃 vlog 插入一条 record */ + Status AddRecord(const Slice& slice); + /* 更新当前活跃 vlog 的头部位置 */ + Status SetHead(size_t offset); + /* 当前活跃 vlog 的写缓冲的数据全部写入磁盘 */ + Status Sync(); + /* 从某个 vlog 中获取 value */ + Status FetchValueFromVlog(Slice record_addr, std::string* value); + /* 设置当前活跃 vlog */ + void SetCurrentVlog(uint64_t vlog_no); + + private: + /* 管理所有 vlog 的编号和信息 */ + std::map vlog_manager_; + /* 记录正在 GC 的 vlog 集合 */ + std::set gc_vlog_set_; + /* 记录触发 GC 的过期阈值 */ + uint64_t expired_threshold_; + /* 记录当前活跃的 vlog 编号 */ + uint64_t cur_vlog_; +}; + +} // namespace vlog +} // namespace leveldb + +#endif // LEVELDB_VLOG_MANAGER_H diff --git a/db/vlog_reader.h b/db/vlog_reader.h new file mode 100644 index 0000000..b4c2baa --- /dev/null +++ b/db/vlog_reader.h @@ -0,0 +1,35 @@ +#ifndef LEVELDB_VLOG_READER_H +#define LEVELDB_VLOG_READER_H + +#include +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class RandomAccessFile; + +namespace vlog { + +class VlogInfo; +class VlogManager; + +class VlogReader { + public: + VlogReader(uint32_t vlog_no); + ~VlogReader() = default; + + /* 在 vlog_offset 处往后读取一条 record 的 value */ + Status Get(uint64_t vlog_offset, std::string* value); + + private: + VlogInfo* vlog_info_; + RandomAccessFile* vlog_; + + friend class VlogManager; +}; + +} // namespace vlog +} // namespace leveldb + +#endif // LEVELDB_VLOG_READER_H diff --git a/db/vlog_writer.h b/db/vlog_writer.h new file mode 100644 index 0000000..afc07d7 --- /dev/null +++ b/db/vlog_writer.h @@ -0,0 +1,39 @@ +#ifndef LEVELDB_VLOG_WRITER_H +#define LEVELDB_VLOG_WRITER_H + +#include +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +namespace vlog { + +class VlogInfo; +class VlogManager; + +class VlogWriter { + public: + explicit VlogWriter(WritableFile* vlog); + ~VlogWriter(); + + /* 往 vlog 的写缓存写入一条 kv 记录 */ + Status AddRecord(const Slice& slice); + + private: + VlogWriter() = default; + + VlogInfo* vlog_info_; + WritableFile* vlog_; + + VlogWriter(const VlogWriter&); + VlogWriter& operator=(const VlogWriter&); + + friend class VlogManager; +}; + +} // namespace vlog +} // namespace leveldb + +#endif // LEVELDB_VLOG_WRITER_H diff --git a/include/leveldb/options.h b/include/leveldb/options.h index d755f46..d87c112 100644 --- a/include/leveldb/options.h +++ b/include/leveldb/options.h @@ -145,6 +145,12 @@ struct LEVELDB_EXPORT Options { // Many applications will benefit from passing the result of // NewBloomFilterPolicy() here. const FilterPolicy* filter_policy = nullptr; + + // vlog 过期 kv 计数器触发 GC 的阈值 + int expired_threshold; + + // vlog 文件大小上限 + int max_vlog_size = 64 * 1024 * 1024; }; // Options that control read operations