Browse Source

complete function :Get_fields

master
王雪飞 8 months ago
parent
commit
b97969e546
3 changed files with 166 additions and 95 deletions
  1. +71
    -2
      db/db_impl.cc
  2. +5
    -0
      db/db_impl.h
  3. +90
    -93
      test/db_test3.cc

+ 71
- 2
db/db_impl.cc View File

@ -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) {

+ 5
- 0
db/db_impl.h View File

@ -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 {

+ 90
- 93
test/db_test3.cc View File

@ -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<std::string> 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<std::chrono::milliseconds>(
@ -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());

Loading…
Cancel
Save