From b97969e546ac0d26227bc869de69ba6167f693d5 Mon Sep 17 00:00:00 2001 From: wangxuefei <10225501435@stu.ecnu.edu.cn> Date: Wed, 1 Jan 2025 09:14:23 +0800 Subject: [PATCH] complete function :Get_fields --- db/db_impl.cc | 73 +++++++++++++++++++++- db/db_impl.h | 5 ++ test/db_test3.cc | 183 +++++++++++++++++++++++++++---------------------------- 3 files changed, 166 insertions(+), 95 deletions(-) diff --git a/db/db_impl.cc b/db/db_impl.cc index 93cda85..7a0dcc5 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1188,11 +1188,24 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, slot_page_->get_slot(slot_num, &sc); vlog_set_->get_value(sc.vlog_num, sc.value_offset, &vlog_value); *value = vlog_value; - std::cout << "value from value_log: " << vlog_value << std::endl; // TODO(end) return s; } +Status DBImpl::Get_Fields(const ReadOptions& options, const Slice& key, + FieldArray* fields) { + // Todo(begin) + std::string value; + Status s = Get(options, key, &value); + if (!s.ok()) { + return s; + } + std::cout << "value from value_log: " << key.ToString() << value << std::endl; + *fields = DeserializeValue(value); + return Status::OK(); + // TODO(end) +} + Iterator* DBImpl::NewIterator(const ReadOptions& options) { SequenceNumber latest_snapshot; uint32_t seed; @@ -1548,6 +1561,62 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { v->Unref(); } +// Todo(begin) +// 反序列化函数,将字符串解码为字段数组 +FieldArray DBImpl::DeserializeValue(const std::string& value_str) { + // 存放解析后的字段数组 + FieldArray fields; + // 将输入字符串转换为输入流 iss, 方便读取 + std::istringstream iss(value_str); + std::string content; + // 临时存放读取的数据 + char buffer[100]; + // 读取长度(定长,16比特) + iss.read(buffer, 16); + buffer[16] = '\0'; + size_t total_length = std::stoi(buffer); + // std::cout << "读取到的总长度为: " << total_length << std::endl; + std::string value_content(value_str.begin() + 16, value_str.begin() + 16 + total_length); + // std::cout << value_content << std::endl; + std::istringstream iss_content(value_content); + iss_content.read(buffer, sizeof(size_t)); + buffer[sizeof(size_t)] = '\0'; + std::string slot_num = buffer; + // 读取属性个数 + iss_content.read(buffer, 16); + // 在第17个比特位处添加终结符,确保字符串以终结符结尾 + buffer[16] = '\0'; + // 将 buffer 中的内容转化为整数并赋值给 field_count + int field_count = std::stoi(buffer); + // std::cout << "读取到的字段个数为: " << field_count << std::endl; + + for (int i = 0; i < field_count; ++i) { + Field field; + // 读取属性名长度(定长,16比特) + iss_content.read(buffer, 16); + buffer[16] = '\0'; + int name_length = std::stoi(buffer); + // std::cout << "读取到的属性名长度为: " << name_length << std::endl; + // 读取属性名(变长) + field.name.resize(name_length); + iss_content.read(&field.name[0], name_length); + // std::cout << "读取到的属性名为: " << field.name << std::endl; + // 读取属性值长度(定长,16比特) + iss_content.read(buffer, 16); + buffer[16] = '\0'; + int value_length = std::stoi(buffer); + // std::cout << "读取到的属性值长度为: " << value_length << std::endl; + // 读取属性值(变长) + field.value.resize(value_length); + iss_content.read(&field.value[0], value_length); + // std::cout << "读取到的属性值为: " << field.value << std::endl; + fields.push_back(field); + } + return fields; +} +// Todo(end) +// Todo(begin) +// 序列化函数,将字段数组序列化为字符串 std::string DBImpl::SerializeValue(const FieldArray& fields) { // 创建并初始化一个字符串流 oss,用于逐步构建最终的序列化字符串 std::ostringstream oss_temp; @@ -1571,9 +1640,9 @@ std::string DBImpl::SerializeValue(const FieldArray& fields) { std::ostringstream oss; oss << std::setw(16) << std::setfill('0') << value_length; oss << temp_str; - return oss.str(); } +// Todo(end) // Default implementations of convenience methods that subclasses of DB // can call if they wish Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { diff --git a/db/db_impl.h b/db/db_impl.h index 8eff8b9..36ad039 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -51,6 +51,10 @@ class DBImpl : public DB { Status Write(const WriteOptions& options, WriteBatch* updates) override; Status Get(const ReadOptions& options, const Slice& key, std::string* value) override; + // Todo(begin) + Status Get_Fields(const ReadOptions& options, const Slice& key, + FieldArray* fields) override; + // Todo(end) Iterator* NewIterator(const ReadOptions&) override; const Snapshot* GetSnapshot() override; void ReleaseSnapshot(const Snapshot* snapshot) override; @@ -88,6 +92,7 @@ class DBImpl : public DB { SlotPage *slot_page_; VlogSet *vlog_set_; static std::string SerializeValue(const FieldArray& fields); + static FieldArray DeserializeValue(const std::string& value_str); // TODO(end) // Information for a manual compaction struct ManualCompaction { diff --git a/test/db_test3.cc b/test/db_test3.cc index 8286c28..9c80952 100644 --- a/test/db_test3.cc +++ b/test/db_test3.cc @@ -13,88 +13,88 @@ #include "gtest/gtest.h" using namespace leveldb; -// 序列化函数,将字段数组编码为字符串 -std::string SerializeValue(const FieldArray& fields) { - // 创建并初始化一个字符串流 oss,用于逐步构建最终的序列化字符串 - std::ostringstream oss_temp; - std::string slot_num = "slot_num"; - oss_temp << std::setw(sizeof(size_t)) << std::setfill('0') << slot_num; - // 写入属性个数(定长,16比特),使用std::setw(16)设置宽度,使用std::setfull(0)设置填充字符,将字段数组的大小写入oss中 - oss_temp << std::setw(16) << std::setfill('0') << fields.size(); - for (const auto& field : fields) { - // 写入属性名长度(定长,16比特) - oss_temp << std::setw(16) << std::setfill('0') << field.name.size(); - // 写入属性名(变长) - oss_temp << field.name; - // 写入属性值长度(定长,16比特) - oss_temp << std::setw(16) << std::setfill('0') << field.value.size(); - // 写入属性值(变长) - oss_temp << field.value; - } - std::string temp_str = oss_temp.str(); - size_t value_length = temp_str.size(); - - std::ostringstream oss; - oss << std::setw(16) << std::setfill('0') << value_length; - oss << temp_str; - - std::cout << "value 的长度为: " << value_length << std::endl; - std::cout << "总长度为: " << oss.str().size() << std::endl; - return oss.str(); -} - -// 反序列化函数,将字符串解码为字段数组 -FieldArray ParseValue(const std::string& value_str) { - // 存放解析后的字段数组 - FieldArray fields; - // 将输入字符串转换为输入流 iss, 方便读取 - std::istringstream iss(value_str); - std::string content; - // 临时存放读取的数据 - char buffer[100]; - // 读取长度(定长,16比特) - iss.read(buffer, 16); - buffer[16] = '\0'; - size_t total_length = std::stoi(buffer); - // std::cout << "读取到的总长度为: " << total_length << std::endl; - std::string value_content(value_str.begin() + 16, value_str.begin() + 16 + total_length); - // std::cout << value_content << std::endl; - std::istringstream iss_content(value_content); - iss_content.read(buffer, sizeof(size_t)); - buffer[sizeof(size_t)] = '\0'; - std::string slot_num = buffer; - // 读取属性个数 - iss_content.read(buffer, 16); - // 在第17个比特位处添加终结符,确保字符串以终结符结尾 - buffer[16] = '\0'; - // 将 buffer 中的内容转化为整数并赋值给 field_count - int field_count = std::stoi(buffer); - // std::cout << "读取到的字段个数为: " << field_count << std::endl; - - for (int i = 0; i < field_count; ++i) { - Field field; - // 读取属性名长度(定长,16比特) - iss_content.read(buffer, 16); - buffer[16] = '\0'; - int name_length = std::stoi(buffer); - // std::cout << "读取到的属性名长度为: " << name_length << std::endl; - // 读取属性名(变长) - field.name.resize(name_length); - iss_content.read(&field.name[0], name_length); - // std::cout << "读取到的属性名为: " << field.name << std::endl; - // 读取属性值长度(定长,16比特) - iss_content.read(buffer, 16); - buffer[16] = '\0'; - int value_length = std::stoi(buffer); - // std::cout << "读取到的属性值长度为: " << value_length << std::endl; - // 读取属性值(变长) - field.value.resize(value_length); - iss_content.read(&field.value[0], value_length); - // std::cout << "读取到的属性值为: " << field.value << std::endl; - fields.push_back(field); - } - return fields; -} +//// 序列化函数,将字段数组编码为字符串 +//std::string SerializeValue(const FieldArray& fields) { +// // 创建并初始化一个字符串流 oss,用于逐步构建最终的序列化字符串 +// std::ostringstream oss_temp; +// std::string slot_num = "slot_num"; +// oss_temp << std::setw(sizeof(size_t)) << std::setfill('0') << slot_num; +// // 写入属性个数(定长,16比特),使用std::setw(16)设置宽度,使用std::setfull(0)设置填充字符,将字段数组的大小写入oss中 +// oss_temp << std::setw(16) << std::setfill('0') << fields.size(); +// for (const auto& field : fields) { +// // 写入属性名长度(定长,16比特) +// oss_temp << std::setw(16) << std::setfill('0') << field.name.size(); +// // 写入属性名(变长) +// oss_temp << field.name; +// // 写入属性值长度(定长,16比特) +// oss_temp << std::setw(16) << std::setfill('0') << field.value.size(); +// // 写入属性值(变长) +// oss_temp << field.value; +// } +// std::string temp_str = oss_temp.str(); +// size_t value_length = temp_str.size(); +// +// std::ostringstream oss; +// oss << std::setw(16) << std::setfill('0') << value_length; +// oss << temp_str; +// +// std::cout << "value 的长度为: " << value_length << std::endl; +// std::cout << "总长度为: " << oss.str().size() << std::endl; +// return oss.str(); +//} + +//// 反序列化函数,将字符串解码为字段数组 +//FieldArray ParseValue(const std::string& value_str) { +// // 存放解析后的字段数组 +// FieldArray fields; +// // 将输入字符串转换为输入流 iss, 方便读取 +// std::istringstream iss(value_str); +// std::string content; +// // 临时存放读取的数据 +// char buffer[100]; +// // 读取长度(定长,16比特) +// iss.read(buffer, 16); +// buffer[16] = '\0'; +// size_t total_length = std::stoi(buffer); +// // std::cout << "读取到的总长度为: " << total_length << std::endl; +// std::string value_content(value_str.begin() + 16, value_str.begin() + 16 + total_length); +// // std::cout << value_content << std::endl; +// std::istringstream iss_content(value_content); +// iss_content.read(buffer, sizeof(size_t)); +// buffer[sizeof(size_t)] = '\0'; +// std::string slot_num = buffer; +// // 读取属性个数 +// iss_content.read(buffer, 16); +// // 在第17个比特位处添加终结符,确保字符串以终结符结尾 +// buffer[16] = '\0'; +// // 将 buffer 中的内容转化为整数并赋值给 field_count +// int field_count = std::stoi(buffer); +// // std::cout << "读取到的字段个数为: " << field_count << std::endl; +// +// for (int i = 0; i < field_count; ++i) { +// Field field; +// // 读取属性名长度(定长,16比特) +// iss_content.read(buffer, 16); +// buffer[16] = '\0'; +// int name_length = std::stoi(buffer); +// // std::cout << "读取到的属性名长度为: " << name_length << std::endl; +// // 读取属性名(变长) +// field.name.resize(name_length); +// iss_content.read(&field.name[0], name_length); +// // std::cout << "读取到的属性名为: " << field.name << std::endl; +// // 读取属性值长度(定长,16比特) +// iss_content.read(buffer, 16); +// buffer[16] = '\0'; +// int value_length = std::stoi(buffer); +// // std::cout << "读取到的属性值长度为: " << value_length << std::endl; +// // 读取属性值(变长) +// field.value.resize(value_length); +// iss_content.read(&field.value[0], value_length); +// // std::cout << "读取到的属性值为: " << field.value << std::endl; +// fields.push_back(field); +// } +// return fields; +//} // 根据字段值查找所有包含该字段的 key,遍历 std::vector FindKeysByField(leveldb::DB* db, const Field& field) { @@ -103,10 +103,8 @@ std::vector FindKeysByField(leveldb::DB* db, const Field& field) { for (it->SeekToFirst(); it->Valid() ; it->Next()) { std::string key = it->key().ToString(); - std::string value; - db->Get(leveldb::ReadOptions(), key, &value); - - FieldArray fields = ParseValue(value); + FieldArray fields; + db->Get_Fields(leveldb::ReadOptions(), key, &fields); for (const auto& f : fields) { if (f.name == field.name && f.value == field.value) { keys.push_back(key); @@ -133,8 +131,7 @@ void TestThroughput(leveldb::DB* db, int num_operations) { for (int i = 0; i < num_operations; ++i) { std::string key = "key_" + std::to_string(i); FieldArray fields = {{"name", "Customer" + std::to_string(i)}, {"address", "Address" + std::to_string(i)}, {"phone", "1234567890"}}; - std::string value = SerializeValue(fields); - db->Put(writeOptions, key, value); + db->Put_Fields(writeOptions, key, fields); } auto end_time = std::chrono::steady_clock::now(); @@ -152,9 +149,8 @@ void TestLatency(leveldb::DB* db, int num_operations, std::vector& lat_ // 执行写入操作 std::string key = "key_" + std::to_string(i); FieldArray fields = {{"name", "Customer" + std::to_string(i)}, {"address", "Address" + std::to_string(i)}, {"phone", "1234567890"}}; - std::string value = SerializeValue(fields); - db->Put(writeOptions, key, value); - db->Get(leveldb::ReadOptions(), key, &value); + db->Put_Fields(writeOptions, key, fields); + db->Get_Fields(leveldb::ReadOptions(), key, &fields); end_time = std::chrono::steady_clock::now(); latency = std::chrono::duration_cast( @@ -204,8 +200,9 @@ TEST(TestSchema, Basic) { // 读取并反序列化 std::string value_ret; - db->Get(leveldb::ReadOptions(), key1, &value_ret); - auto fields_ret = ParseValue(value_ret); + FieldArray fields_ret; + db->Get_Fields(leveldb::ReadOptions(), key1, &fields_ret); + // 检查反序列化结果 ASSERT_EQ(fields_ret.size(), fields1.size());