diff --git a/db/db_impl.cc b/db/db_impl.cc index f96d245..d5ec640 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include "db/builder.h" #include "db/db_iter.h" @@ -35,6 +36,7 @@ #include "util/logging.h" #include "util/mutexlock.h" + namespace leveldb { const int kNumNonTableCacheFiles = 10; @@ -123,8 +125,33 @@ static int TableCacheSize(const Options& sanitized_options) { return sanitized_options.max_open_files - kNumNonTableCacheFiles; } + +//Secondary Index ToDo +FieldDb::FieldDb(DB* kv_db, DB* index_db) + : kvDb(kv_db), // 初始化 kvDb 成员变量 + indexDb(index_db), // 初始化 indexDb 成员变量 + fieldWithIndex(), // 初始化字段索引列表 + taskQueue() { // 初始化任务队列 + // 如果需要在构造函数中做额外的初始化操作,可以在这里进行 +} + +FieldDb::~FieldDb() { + // 清空 taskQueue 中的所有任务 + while (!taskQueue.empty()) { + taskQueue.pop(); + } + // 对于 kvDb 和 indexDb,如果它们需要手动释放资源,可以在这里进行处理 + // 注意:通常 leveldb 会负责释放它们的资源,如果不需要手动释放,可以忽略这一步 + // 如果 kvDb 和 indexDb 是由 FieldDb 管理的并且需要释放,可以在此释放 + // delete kvDb; // 假设我们负责销毁 kvDb + // delete indexDb; // 假设我们负责销毁 indexDb +} + +//ToDo end + DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) - : env_(raw_options.env), + : /*Secondary Index ToDo*/ FieldDb(kvDb, indexDb), // 调用 FieldDb 构造函数初始化 kvDb 和 indexDb /*ToDo end */ + env_(raw_options.env), internal_comparator_(raw_options.comparator), internal_filter_policy_(raw_options.filter_policy), options_(SanitizeOptions(dbname, &internal_comparator_, @@ -596,6 +623,90 @@ void DBImpl::CompactRange(const Slice* begin, const Slice* end) { } } +//Secondary index ToDo +// 定义字段类型别名 +Status DBImpl::CreateIndexOnField(const std::string& fieldName) { + // 首先检查字段是否已经创建了索引 + for (const auto& field : fieldWithIndex) { + if (field == fieldName) { + return Status::InvalidArgument("Index already exists for this field"); + } + } + + // 将索引字段添加到 fieldWithIndex 列表中 + fieldWithIndex.push_back(fieldName); + + // 在索引数据库中为字段创建索引(这只是一个简单的例子,实际的索引创建可能会更复杂) + std::string key = "index:" + fieldName; + std::string value = "index_created"; + Status s = indexDb->Put(WriteOptions(), Slice(key), Slice(value)); + if (!s.ok()) { + return s; + } + + return Status::OK(); +} + +Status DBImpl::DeleteIndex(const std::string& fieldName) { + auto it = std::find(fieldWithIndex.begin(), fieldWithIndex.end(), fieldName); + if (it == fieldWithIndex.end()) { + return Status::NotFound("Index not found for this field"); + } + + // 从列表中移除该字段 + fieldWithIndex.erase(it); + + // 删除索引数据库中的条目 + std::string key = "index:" + fieldName; + Status s = indexDb->Delete(WriteOptions(), Slice(key)); + if (!s.ok()) { + return s; + } + + return Status::OK(); +} + +Status DBImpl::QueryByIndex(const std::string& fieldName, std::vector* results) { + // 检查该字段是否有索引 + auto it = std::find(fieldWithIndex.begin(), fieldWithIndex.end(), fieldName); + if (it == fieldWithIndex.end()) { + return Status::NotFound("No index found for this field"); + } + + // 执行查询操作(这是一个简单的查询方法,实际应用中可能会更复杂) + std::string key = "index:" + fieldName; + std::string value; + Status s = indexDb->Get(ReadOptions(), Slice(key), &value); + if (!s.ok()) { + return s; + } + + // 假设我们通过值可以获取到索引的内容,添加到结果列表中 + results->push_back(value); // 这里可以根据实际需求来处理查询结果 + + return Status::OK(); +} + +Status DBImpl::EncodeIndexKey(const std::string& fieldName, const std::string& key, std::string* encodedKey) { + // 简单的编码示例,可以根据需求修改 + *encodedKey = fieldName + ":" + key; + return Status::OK(); +} + +Status DBImpl::DecodeIndexKey(const std::string& encodedKey, std::string* fieldName, std::string* originalKey) { + size_t pos = encodedKey.find(':'); + if (pos == std::string::npos) { + return Status::InvalidArgument("Invalid encoded key"); + } + + *fieldName = encodedKey.substr(0, pos); + *originalKey = encodedKey.substr(pos + 1); + return Status::OK(); +} + + +// ToDo end + void DBImpl::TEST_CompactRange(int level, const Slice* begin, const Slice* end) { assert(level >= 0); @@ -1542,6 +1653,7 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) { return s; } + Snapshot::~Snapshot() = default; Status DestroyDB(const std::string& dbname, const Options& options) { diff --git a/db/db_impl.h b/db/db_impl.h index c7b0172..eb6841a 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "db/dbformat.h" #include "db/log_writer.h" @@ -26,7 +27,7 @@ class Version; class VersionEdit; class VersionSet; -class DBImpl : public DB { +class DBImpl : /*Secondary Index ToDo*/ public DB , public FieldDb/*ToDo end*/{ public: DBImpl(const Options& options, const std::string& dbname); @@ -51,6 +52,14 @@ class DBImpl : public DB { // Extra methods (for testing) that are not in the public DB interface + //Secondary Index ToDo + // 重写 FieldDb 中的索引相关方法 + Status CreateIndexOnField(const std::string& fieldName) override; + Status DeleteIndex(const std::string& fieldName) override; + Status QueryByIndex(const std::string& fieldName, std::vector* results) override; + //ToDo end + + // Compact any files in the named level that overlap [*begin,*end] void TEST_CompactRange(int level, const Slice* begin, const Slice* end); @@ -155,6 +164,14 @@ class DBImpl : public DB { return internal_comparator_.user_comparator(); } + //Secondary Index ToDo + // 为 FieldDb 定义的成员变量 + DB* kvDb; // 原始数据库(键值存储) + DB* indexDb; // 索引数据库(二级索引) + std::vector fieldWithIndex; // 存储已经索引的字段 + std::queue> taskQueue; + //ToDo end + // Constant after construction Env* const env_; const InternalKeyComparator internal_comparator_; @@ -203,8 +220,17 @@ class DBImpl : public DB { Status bg_error_ GUARDED_BY(mutex_); CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_); + + //Secondary Index ToDo + // Helper methods to interact with the underlying database + Status EncodeIndexKey(const std::string& fieldName, const std::string& key, std::string* encodedKey); + Status DecodeIndexKey(const std::string& encodedKey, std::string* fieldName, std::string* originalKey); + //ToDo end }; + + + // Sanitize db options. The caller should delete result.info_log if // it is not equal to src.info_log. Options SanitizeOptions(const std::string& db, diff --git a/include/leveldb/db.h b/include/leveldb/db.h index bf4eec5..755c119 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -7,6 +7,8 @@ #include #include +#include +#include #include "leveldb/export.h" #include "leveldb/iterator.h" @@ -145,12 +147,52 @@ class LEVELDB_EXPORT DB { // Therefore the following call will compact the entire database: // db->CompactRange(nullptr, nullptr); virtual void CompactRange(const Slice* begin, const Slice* end) = 0; +}; + +// Secondary index ToDo +// Definition of the FieldDb class to manage kvDb and indexDb +class LEVELDB_EXPORT FieldDb { + public: + FieldDb(DB* kv_db, DB* index_db); + virtual ~FieldDb(); + + // 静态 Open 函数声明 + static Status Open(const Options& options, const std::string& dbname, FieldDb** field_db); + + // Add an index on the specified field + virtual Status CreateIndexOnField(const std::string& fieldName) = 0; + + // Remove an index on the specified field + virtual Status DeleteIndex(const std::string& fieldName) = 0; + + // Query the database using an index + virtual Status QueryByIndex(const std::string& fieldName, std::vector* results) = 0; - // ----------------------------For TTL----------------------------- - // 为当前key设置ttl,过期后自动失效 virtual Status Put(const WriteOptions& options, const Slice& key, - const Slice& value, uint64_t ttl) = 0; + const Slice& value) = 0; + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value) = 0; + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + virtual const Snapshot* GetSnapshot() = 0; + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; + + private: + // Helper methods + virtual Status EncodeIndexKey(const std::string& fieldName, const std::string& key, std::string* encodedKey) = 0; + virtual Status DecodeIndexKey(const std::string& encodedKey, std::string* fieldName, std::string* originalKey) = 0; + + DB* kvDb; // Original database (key-value store) + DB* indexDb; // Index database (secondary index) + std::vector fieldWithIndex; // List of fields with indexes + std::queue> taskQueue; }; +// ToDo end // Destroy the contents of the specified database. // Be very careful using this method.