ソースを参照

fields v1: finish DBImpl interface and Class Fields definition

main
VirgilZhu 9ヶ月前
コミット
64fd7be5f8
8個のファイルの変更365行の追加26行の削除
  1. +12
    -2
      CMakeLists.txt
  2. +47
    -22
      README.md
  3. +17
    -0
      db/db_impl.cc
  4. +4
    -0
      db/db_impl.h
  5. +165
    -0
      db/fields.cpp
  6. +63
    -0
      db/fields.h
  7. +2
    -2
      include/leveldb/db.h
  8. +55
    -0
      test/value_field_test.cc

+ 12
- 2
CMakeLists.txt ファイルの表示

@ -117,10 +117,12 @@ endif(BUILD_SHARED_LIBS)
# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
include(GNUInstallDirs)
add_library(leveldb "")
add_library(leveldb)
target_sources(leveldb
PRIVATE
"${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
"db/fields.cpp"
"db/fields.h"
"db/builder.cc"
"db/builder.h"
"db/c.cc"
@ -521,11 +523,19 @@ endif(LEVELDB_INSTALL)
add_executable(db_test2
"${PROJECT_SOURCE_DIR}/test/db_test2.cc"
test/value_field_test.cc
)
target_link_libraries(db_test2 PRIVATE leveldb)
add_executable(ttl_test
"${PROJECT_SOURCE_DIR}/test/ttl_test.cc"
test/value_field_test.cc
)
target_link_libraries(ttl_test PRIVATE leveldb gtest)
target_link_libraries(ttl_test PRIVATE leveldb gtest)
add_executable(value_field_test
"${PROJECT_SOURCE_DIR}/test/value_field_test.cc"
test/value_field_test.cc
)
target_link_libraries(value_field_test PRIVATE leveldb gtest)

+ 47
- 22
README.md ファイルの表示

@ -72,30 +72,55 @@
+ `class Fields`
```c++
class Fields {
public:
// 从 FieldArray 构造
explicit Fields(FieldArray field_array);
// 从字符串解码构造
explicit Fields(const std::string& value_str);
class Fields {
private:
FieldArray fields_;
public:
/* 从 FieldArray 构造 */
explicit Fields(const FieldArray& fields);
/* 从单个 Field 构造 */
explicit Fields(const Field& field);
/* 只传参 field_name 数组的构造 */
explicit Fields(const std::vector<std::string>& field_names);
Fields() = default;
~Fields() = default;
~Fields();
/* 根据 field_name 从小到大进行排序,减少通过 field_name 遍历 Fields 的耗时 */
void SortFields();
/* 更新/插入单个字段值,插入后会进行 Fields 排序,减少通过 field_name 遍历 Fields 的耗时 */
void UpdateField(const std::string& field_name, const std::string& field_value);
void UpdateField(const Field& field);
/* 更新/插入多个字段值 */
void UpdateFields(const std::vector<std::string>& field_names, const std::vector<std::string>& field_values);
void UpdateFields(const FieldArray& fields);
// 更新字段值
void update_field(const std::string& name, const std::string& value);
// 获取字段
Field get_field(const std::string& name) const;
// 检查字段是否存在
bool has_field(const std::string& name) const;
// 序列化字段数组为字符串
std::string Serialize() const;
// 重载运算符 [] 用于访问字段值
std::string operator[](const std::string& name) const;
// 重载运算符 [] 用于修改字段值
std::string& operator[](const std::string& name);
// 重载运算符 == 用于比较两个 Fields 是否相等
bool operator==(const Fields& other) const;
};
/* 删除单个字段 */
void DeleteField(const std::string& field_name);
/* 删除多个字段 */
void DeleteFields(const std::vector<std::string>& field_names);
/* 序列化 Field 或 FieldArray 为 value 字符串 */
/* static 修饰的函数序列化/反序列化无需访问一个 Fields 对象的 fields_ */
static std::string SerializeValue(const FieldArray& fields);
static std::string SerializeValue(const Field& field);
std::string SerializeValue() const;
/* 反序列化 value 字符串为 Fields */
static Fields ParseValue(const std::string& value_str);
/* 获取字段 */
Field GetField(const std::string& field_name) const;
/* 检查字段是否存在 */
bool HasField(const std::string& field_name) const;
/* 重载运算符 [] 用于访问字段值 */
std::string operator[](const std::string& field_name) const;
/* 重载运算符 [] 用于修改字段值 */
std::string& operator[](const std::string& field_name);
};
```
### 4.2 KV 分离

+ 17
- 0
db/db_impl.cc ファイルの表示

@ -12,6 +12,7 @@
#include <string>
#include <vector>
#include "fields.h"
#include "db/builder.h"
#include "db/db_iter.h"
#include "db/dbformat.h"
@ -1193,6 +1194,22 @@ void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) {
snapshots_.Delete(static_cast<const SnapshotImpl*>(snapshot));
}
/*** DBImpl 类关于 Fields 类的 Put、Get 接口 ***/
Status DBImpl::PutFields(const WriteOptions& o, const Slice& key, const Fields& fields) {
return DBImpl::Put(o, key, Slice(fields.SerializeValue()));
}
Status DBImpl::GetFields(const ReadOptions& o, const Slice& key, Fields& fields) {
std::string value_str;
Status s = DBImpl::Get(o, key, &value_str);
if (!s.ok()) return s;
fields = Fields::ParseValue(value_str);
return Status::OK();
}
/**************************************************/
// Convenience methods
Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) {
return DB::Put(o, key, val);

+ 4
- 0
db/db_impl.h ファイルの表示

@ -25,6 +25,7 @@ class TableCache;
class Version;
class VersionEdit;
class VersionSet;
class Fields;
class DBImpl : public DB {
public:
@ -36,6 +37,9 @@ class DBImpl : public DB {
~DBImpl() override;
// Implementations of the DB interface
Status PutFields(const WriteOptions&, const Slice& key, const Fields& fields);
Status GetFields(const ReadOptions& options, const Slice& key, Fields& fields);
Status Put(const WriteOptions&, const Slice& key,
const Slice& value) override;
Status Delete(const WriteOptions&, const Slice& key) override;

+ 165
- 0
db/fields.cpp ファイルの表示

@ -0,0 +1,165 @@
#include "fields.h"
#include "util/coding.h"
#include <iostream>
#include <utility>
namespace leveldb {
/* 构造函数 */
Fields::Fields(FieldArray fields)
: fields_(std::move(fields)) {
SortFields();
}
Fields::Fields(const Field& field)
: fields_({field}) {}
Fields::Fields(const std::vector<std::string>& field_names) {
for (const auto& name : field_names) {
fields_.emplace_back(name, "");
}
SortFields();
}
/* 根据 field_name 从小到大进行排序,减少通过 field_name 遍历 Fields 的耗时 */
void Fields::SortFields() {
std::sort(fields_.begin(), fields_.end(), [](const Field& a, const Field& b) {
return a.first < b.first;
});
}
/* 更新/插入单个字段值 */
void Fields::UpdateField(const std::string& field_name, const std::string& field_value) {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first > field_name) {
fields_.insert(iter, {field_name, field_value});
return;
}
if ((*iter).first == field_name) {
(*iter).second = field_value;
return;
}
}
fields_.emplace_back(field_name, field_value);
}
void Fields::UpdateField(const Field& field) {
UpdateField(field.first, field.second);
}
/* 更新/插入多个字段值 */
void Fields::UpdateFields(const std::vector<std::string>& field_names, const std::vector<std::string>& field_values) {
if (field_names.size() != field_values.size()) {
std::cerr << "UpdateFields Failed: field_name and field_values must have the same size." << std::endl;
return;
}
for (size_t i = 0; i < field_names.size(); ++i) {
UpdateField(field_names[i], field_values[i]);
}
}
void Fields::UpdateFields(const FieldArray& fields) {
for (const auto& field : fields) {
UpdateField(field);
}
}
/* 删除单个字段 */
void Fields::DeleteField(const std::string& field_name) {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first > field_name) return;
if ((*iter).first == field_name) {
fields_.erase(iter);
return;
}
}
}
/* 删除多个字段 */
void Fields::DeleteFields(const std::vector<std::string>& field_names) {
for (auto &name : field_names) {
if (fields_.empty()) return;
DeleteField(name);
}
}
/* 序列化 Field 或 FieldArray 为 value 字符串 */
std::string Fields::SerializeValue(const FieldArray& fields) {
std::string value_str;
for (const auto& field : fields) {
std::string field_str = SerializeValue(field);
value_str += field_str;
}
return value_str;
}
std::string Fields::SerializeValue(const Field& field) {
std::string value_str;
PutLengthPrefixedSlice(&value_str, Slice(field.first));
PutLengthPrefixedSlice(&value_str, Slice(field.second));
return value_str;
}
std::string Fields::SerializeValue() const {
return SerializeValue(fields_);
}
/* 反序列化 value 字符串为 Fields */
Fields Fields::ParseValue(const std::string& value_str) {
Fields fields;
Slice value_slice(value_str);
while (!value_slice.empty()) {
Slice field_name;
Slice field_value;
if (!GetLengthPrefixedSlice(&value_slice, &field_name)) break;
if (!GetLengthPrefixedSlice(&value_slice, &field_value)) break;
fields.UpdateField(field_name.ToString(), field_value.ToString());
}
return fields;
}
/* 获取字段 */
Field Fields::GetField(const std::string& field_name) const {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first == field_name) return *iter;
if ((*iter).first > field_name || iter == fields_.end() - 1) {
std::cerr << "GetField Failed: field name [" + field_name + "] doesn't exist, return {}." << std::endl;
return {};
}
}
}
/* 检查字段是否存在 */
bool Fields::HasField(const std::string& field_name) const {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first == field_name) return true;
if ((*iter).first > field_name || iter == fields_.end() - 1) return false;
}
}
/* 重载运算符 [] 用于访问字段值 */
std::string Fields::operator[](const std::string& field_name) const {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first == field_name) return (*iter).second;
if ((*iter).first > field_name || iter == fields_.end() - 1) {
static const std::string empty_str;
std::cerr << "GetField Failed: field name [" + field_name + "] doesn't exist." << std::endl;
return empty_str;
}
}
}
std::string& Fields::operator[](const std::string& field_name) {
for (auto iter = fields_.begin(); iter != fields_.end(); iter++) {
if ((*iter).first == field_name) return (*iter).second;
if ((*iter).first > field_name) {
return fields_.insert(iter, {field_name, ""})->second;
}
}
fields_.emplace_back(field_name, "");
return fields_.back().second;
}
} // namespace leveldb

+ 63
- 0
db/fields.h ファイルの表示

@ -0,0 +1,63 @@
#ifndef LEVELDB_FIELDS_H
#define LEVELDB_FIELDS_H
#include "vector"
#include "leveldb/db.h"
namespace leveldb {
using Field = std::pair<std::string, std::string>;
using FieldArray = std::vector<Field>;
class Fields {
private:
FieldArray fields_;
public:
/* 从 FieldArray 构造 */
explicit Fields(FieldArray fields);
/* 从单个 Field 构造 */
explicit Fields(const Field& field);
/* 只传参 field_name 数组的构造 */
explicit Fields(const std::vector<std::string>& field_names);
Fields() = default;
~Fields() = default;
/* 根据 field_name 从小到大进行排序,减少通过 field_name 遍历 Fields 的耗时 */
void SortFields();
/* 更新/插入单个字段值,插入后会进行 field_name 的排序 */
void UpdateField(const std::string& field_name, const std::string& field_value);
void UpdateField(const Field& field);
/* 更新/插入多个字段值 */
void UpdateFields(const std::vector<std::string>& field_names, const std::vector<std::string>& field_values);
void UpdateFields(const FieldArray& fields);
/* 删除单个字段 */
void DeleteField(const std::string& field_name);
/* 删除多个字段 */
void DeleteFields(const std::vector<std::string>& field_names);
/* 序列化 Field 或 FieldArray 为 value 字符串 */
static std::string SerializeValue(const FieldArray& fields);
static std::string SerializeValue(const Field& field);
std::string SerializeValue() const;
/* 反序列化 value 字符串为 Fields */
static Fields ParseValue(const std::string& value_str);
/* 获取字段 */
Field GetField(const std::string& field_name) const;
/* 检查字段是否存在 */
bool HasField(const std::string& field_name) const;
/* 重载运算符 [] 用于访问字段值 */
std::string operator[](const std::string& field_name) const;
/* 重载运算符 [] 用于修改字段值 */
std::string& operator[](const std::string& field_name);
};
} // namespace leveldb
#endif // LEVELDB_FIELDS_H

+ 2
- 2
include/leveldb/db.h ファイルの表示

@ -148,8 +148,8 @@ class LEVELDB_EXPORT DB {
// ----------------------------For TTL-----------------------------
// key设置ttl
virtual Status Put(const WriteOptions& options, const Slice& key,
const Slice& value, uint64_t ttl) = 0;
// virtual Status Put(const WriteOptions& options, const Slice& key,
// const Slice& value, uint64_t ttl) = 0;
};
// Destroy the contents of the specified database.

+ 55
- 0
test/value_field_test.cc ファイルの表示

@ -0,0 +1,55 @@
#include "gtest/gtest.h"
#include "leveldb/db.h"
#include "db/fields.h"
using namespace leveldb;
constexpr int value_size = 2048;
constexpr int data_size = 128 << 20;
Status OpenDB(std::string dbName, DB **db) {
Options options;
options.create_if_missing = true;
return DB::Open(options, dbName, db);
}
TEST(TestValueField, ReadValueField) {
DB *db;
if(OpenDB("testdb", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
std::string key = "k_1";
FieldArray fields = {
{"name", "Customer#000000001"},
{"address", "IVhzIApeRb"},
{"phone", "25-989-741-2988"}
};
// 序列化并插入
std::string value = SerializeValue(fields);
db->Put(WriteOptions(), key, value);
// 读取并反序列化
std::string value_ret;
db->Get(ReadOptions(), key, &value_ret);
auto fields_ret = ParseValue(value_ret);
}
int main(int argc, char** argv) {
// All tests currently run with the same read-only file limits.
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

読み込み中…
キャンセル
保存